Create an application pool that uses .NET 4.0 - c#

I use the following code to create a app pool:
var metabasePath = string.Format(#"IIS://{0}/W3SVC/AppPools", serverName);
DirectoryEntry newpool;
DirectoryEntry apppools = new DirectoryEntry(metabasePath);
newpool = apppools.Children.Add(appPoolName, "IIsApplicationPool");
newpool.CommitChanges();
How do I specify that the app pool should use .NET Framework 4.0?

I see from the tags you're using IIS7. Unless you absolutely have to, don't use the IIS6 compatibility components. Your preferred approach should be to use the Microsoft.Web.Administration managed API.
To create an application pool using this and set the .NET Framework version to 4.0, do this:
using Microsoft.Web.Administration;
...
using(ServerManager serverManager = new ServerManager())
{
ApplicationPool newPool = serverManager.ApplicationPools.Add("MyNewPool");
newPool.ManagedRuntimeVersion = "v4.0";
serverManager.CommitChanges();
}
You should add a reference to Microsoft.Web.Administration.dll which can be found in:
%SYSTEMROOT%\System32\InetSrv

newpool.Properties["ManagedRuntimeVersion"].Value = "v4.0";
Will do the same thing as the Microsoft.Web.Administration.dll but using DirectoryEntry
Also
newPool.InvokeSet("ManagedPipelineMode", new object[] { 0 });
Will switch to integrated or classic pipeline mode using DirectoryEntry.

The other answers are better in your particular scenario, but in general keep in mind that you can use the appcmd tool to do this: https://technet.microsoft.com/en-us/library/cc731784%28v=ws.10%29.aspx. Specifically:
appcmd add apppool /name: string /managedRuntimeVersion: string /managedPipelineMode: Integrated | Classic

Related

Performance degradation when using CrmServiceClient and AuthType OAuth in Dataverse

I've got an MVC.NET solution that calls the Dataverse API and I'm seeing a significant performance degradation when using CrmServiceClient and AuthType=OAuth compared with the (soon to be deprecated) WS-Trust connection (AuthType=Office365)
This is the code used for creating the CrmServiceClient connection (AuthType=OAuth)
var conn = new CrmServiceClient(connectionString);
var service = (IOrganizationService) conn.OrganizationWebProxyClient ?? conn.OrganizationServiceProxy;
and this is the code used for creating WS-Trust connection (AuthType=Office365)
var target = CrmConnection.Parse(connectionString);
target.ServiceConfigurationInstanceMode = ServiceConfigurationInstanceMode.PerName;
var service = (OrganizationService) CrmConfigurationManager.CreateService(target, "DataverseServiceName");
has anyone experienced the same issue?
In our case the issue was that we were using an old version of the CrmSdk, using the latest version (9.0.2.42) solved our problem
https://www.nuget.org/packages/Microsoft.CrmSdk.CoreAssemblies/9.0.2.42
We also have issues with impersonation when setting the caller id (https://learn.microsoft.com/en-us/dotnet/api/microsoft.xrm.tooling.connector.crmserviceclient.callerid?view=dataverse-sdk-latest#microsoft-xrm-tooling-connector-crmserviceclient-callerid), if you are running several threads and initiating multiple connections with different callerids, we found that it's not thread safe and some calls to impersonate one user might get mixed up by another user even if:
disablecrossthreadsafeties is set to false (https://learn.microsoft.com/en-us/dotnet/api/microsoft.xrm.tooling.connector.crmserviceclient.disablecrossthreadsafeties?view=dataverse-sdk-latest#microsoft-xrm-tooling-connector-crmserviceclient-disablecrossthreadsafeties)
RequireNewInstance is set to true (https://learn.microsoft.com/en-us/power-apps/developer/data-platform/xrm-tooling/use-connection-strings-xrm-tooling-connect#connection-string-parameters)
We ended up having to cache each IOrganizationService per callerid to prevent it

Sharepoint CSOM Authentication issue with .NET Core

I'm new to Sharepoint online, and don't have an own account (yet), just an username/password from a client.
Need to build a service that gets the folder structure and archives from Sharepoint. And then allows to up/download archives.
Since the package
Microsoft.SharePointOnline.CSOM
is not compatible with .NET Core, I'm using this github solution that seems to cover the main functionality in an equal way: https://github.com/OneBitSoftware/NetCore.CSOM
I think there is nothing wrong with that so far - but when trying to connect using
SharePointOnlineCredentials
...I'm getting the error
PPCRL_REQUEST_E_PARTNER_HAS_NO_ASYMMETRIC_KEY
So I guess there's some account setting missing on the server side? Or am I following a wrong approach? I would have no problem implementing an OAuth access to get a Bearer token, but which API would that be, and how can I register an app for Sharepoint?
My research about API's and this particular error didn't result in anything yet, so I'm reaching out for help here.
Get NuGet package TTCUE.NetCore.SharepointOnline.CSOM.16.1.8029.1200.
You can also download an official package Microsoft.SharePointOnline.CSOM but it will attach wrong dlls to your project and you would need to change them according to the link from a different answer here - https://rajujoseph.com/getting-net-core-and-sharepoint-csom-play-nice/
Note - Your .NET Core project will compile, but it doesn't mean that it will work on, for example, linux. Those CSOM dlls are not finished and Microsoft is still working on them.(for a loooong time...)
Check the example below:
Create a .NET Core console app.
Add the references: Microsoft.SharePoint.Client.Portable.dll, Microsoft.SharePoint.Client.Runtime.Portable.dll, and Microsoft.SharePoint.Client.Runtime.Windows.dll.
Note: If the project has references to Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll, please remove them.
These references can be accessed by installing CSOM library into another project, and then navigating to installed nuget packages in the file directory:
c:\Users\user\\.nuget\packages\microsoft.sharepointonline.csom\\(version)\lib\netcore45
Add the code below to the .NET Core 2.0 console application:
using System;
using Microsoft.SharePoint.Client;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
string targetSiteURL = #"https://xxx.sharepoint.com/sites/xxx";
var login = "xxx#xx.onmicrosoft.com";
var password = "xxx";
SharePointOnlineCredentials onlineCredentials = new SharePointOnlineCredentials(login, password);
ClientContext ctx = new ClientContext(targetSiteURL);
ctx.Credentials = onlineCredentials;
WebCreationInformation wci = new WebCreationInformation();
wci.Url = "Site1"; // This url is relative to the url provided in the context
wci.Title = "Site 1";
wci.UseSamePermissionsAsParentSite = true;
wci.WebTemplate = "STS#0";
wci.Language = 1033;
var newWeb = ctx.Web.Webs.Add(wci);
ctx.Load(newWeb, w => w.Title);
ctx.ExecuteQueryAsync();
Console.WriteLine("Web title:" + newWeb.Title);
Console.ReadKey();
}
}
}
More information: Getting .NET Core and SharePoint CSOM Play Nice

Using ServiceStack Redis from .net core and connecting to Sentinel setup

I have created a .net core console application and included the ServiceStack.Redis.Core v1.0.23 nuget package. I also have the redis sentinel setup running locally. When I try to connect to redis using the sentinel connection method the application hangs on sentinel.start(). There are no errors returned.
If I create the same application using a windows console application using a standard windows C# project and including the ServiceStack.Redis v4.5.4 nuget package the same connection code works fine.
I have also managed to connect from an .net core application using a single redis instance, but not using the sentinel.
Has anyone else experienced this or know of a way to get this working inside a .net core application?
Code used to try to connect:
var sentinelHosts = new[] { "127.0.0.1:26380", "127.0.0.1:26381", "127.0.0.1:26382" };
var sentinel = new RedisSentinel(sentinelHosts, masterName: "mymaster");
var clientManager = sentinel.Start();
It's a bug, which should be fixed with this commit. sentinel.Start() makes a call to RedisPubSubServer which blocks current thread on .NET Core and that is why control does not return back and hangs. This change will be available on nuget with ServiceStack.Redis.Core v1.0.25 package.

Modifying scriptmaps/handlermappings programmatically

I have some code to create a Virtual Directory programmatically.
I need to edit handler mappings of framework 2.0 to use .net 4.0 (basically run .net 2.0 code under .net 4.0 CLR).
The code below works fine under win 2003 server, but on Windows 2008 server webservicefactoryHandler2.0 is renamed as webservicefactoryHandler4.032_1245.
I don't know how to access/edit this name or infact retain the name and just change its value to \Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll from \Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll.
Dim scriptMapVals As PropertyValueCollection = VDir.Properties("ScriptMaps")
Dim objScriptMaps As ArrayList = New ArrayList()
Dim frameworkVersion As String = "4.0.30319"
Dim versionRegex As Text.RegularExpressions.Regex = New Text.RegularExpressions.Regex("(?<=\\v)\d{1}\.\d{1}\.\d{1,5}(?=\\)")
''Assuming the version will always be something like n.n.nnnnn
Dim scriptMapVal As String
For Each scriptMapVal In scriptMapVals
If scriptMapVal.Contains("Framework") AndAlso scriptMapVal.Contains("asmx") Then
objScriptMaps.Add(Text.RegularExpressions.Regex.Replace(scriptMapVal, versionRegex.ToString, frameworkVersion))
Else
objScriptMaps.Add(scriptMapVal)
End If
Next
VDir.Properties("ScriptMaps").Value = objScriptMaps.ToArray()
VDir.CommitChanges()
Update:
#kev : So basically you are saying to use different code for different version of IIS right? Well while using import "Microsoft.Web.Administration.dll" , do i need to pack it up in my build ? or this is part of all IIS7.0 installables? as Some poeple could have IIS7.0 on Windows XP.
Thanks
gauls
First of all, don't use the IIS6 compatibility API to manipulate IIS7 handler mappings. Use the Microsoft.Web.Administration managed API instead.
However, you're going about this in completely the wrong way. You shouldn't be touching the handler mappings but instead change the managed runtime version for the application pool in in which the application resides.
Add a reference to:
C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll
Then in your code:
using Microsoft.Web.Administration;
...
using (ServerManager serverManager = new ServerManager())
{
ApplicationPool appPool =
serverManager.ApplicationPools.Where(a => a.Name.Equals(appPoolName))
.Single();
appPool.ManagedRuntimeVersion = "v2.0";
serverManager.CommitChanges();
}
I would also recommend NOT using the ADSI compatibility API's at all to manipulate IIS7's configuration. Learn to love and embrace <applicationHost> and forget about thinking in terms of metabase objects in IIS7:
http://www.iis.net/ConfigReference/system.applicationHost
Update:
Further to your question about having code that works with both IIS6 and IIS7 I would thoroughly recommend NOT using the IIS6 compatibility layer for the convenience of having to maintain just one codebase.
The reason for this is that features of IIS7 objects such as HandlerMappings (the equivalent of Script Mappings) are handled differently. The compatibility shim creates what's known as ABO Custom Map objects which lose some of the benefits of proper HandlerMappings. Whilst they work they will create an administrative nightmare in the longer term. Trust me, I've been there.
If you need to detect which version of IIS your running then here is a handy function to do that:
public static int GetIIsMajorVersion()
{
string regKey = #"SOFTWARE\Microsoft\InetStp";
using(RegistryKey key = Registry.LocalMachine.OpenSubKey(regKey, true))
{
return Convert.ToInt32(key.GetValue("MajorVersion"));
}
}
If the return value is 6 then it's IIS6, if it's 7 then you're on IIS 7.x.

Control IIS 7 server from Windows 2003 server programmatically

We run various jobs using a Windows 2003 server. Some of these jobs send app pool commands to web servers running IIS 6 (recycle, start, stop). Now we have a Windows 2008 web server running IIS 7, and we want to send the same commands. This is all done using C#.
This is the code we use to send commands for IIS 6:
var methodToInvoke = "Stop"; // could be "Stop", "Start", or "Recycle"
var co = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.PacketPrivacy
};
var objPath = string.Format("IISApplicationPool.Name='W3SVC/AppPools/{0}'", appPoolName);
var scope = new ManagementScope(string.Format(#"\\{0}\root\MicrosoftIISV2", machineName), co);
using (var mc = new ManagementObject(objPath))
{
mc.Scope = scope;
mc.InvokeMethod(methodToInvoke, null, null);
}
This code doesn't work for IIS 7 due to underlying changes, so we're currently trying this:
using (ServerManager serverManager = ServerManager.OpenRemote(machineName))
{
var appPool = serverManager.ApplicationPools[appPoolName];
if (appPool != null)
{
appPool.Stop(); // or app.Start() or app.Recycle()
serverManager.CommitChanges();
}
}
The above code works fine on my workstation, which runs Windows 7 (and, thus, IIS 7.5). However, it does not work when I deploy this code to our application server. It get this error:
System.InvalidCastException:
Unable to cast COM object of type 'System.__ComObject' to interface type
'Microsoft.Web.Administration.Interop.IAppHostWritableAdminManager'.
This operation failed because the QueryInterface call on the COM component for the
interface with IID '{FA7660F6-7B3F-4237-A8BF-ED0AD0DCBBD9}' failed due to the following error:
Interface not registered (Exception from HRESULT: 0x80040155).
From my research, this is due to the fact that IIS 7 is not available on the Windows Server 2003 server. (I did include the Microsoft.Web.Administration.dll file.)
So my questions are:
Is it possible for the above code for IIS 7 to work at all from a Windows 2003 server?
If no to #1, is there a better way of doing this?
From reading around it doesn't appear to be possible to do what you're looking for. It's not enough to include the dll files.
According to http://forums.iis.net/t/1149274.aspx..
In order to use Microsoft.Web.Administration you need to have IIS installed, at the bare minimum you need to install the Configuration API's which are brought through installing the Management Tools.
Unfortunately there is no SDK that enables this and it has several dependencies on other components that wouldn't let you just take it to another machine and make it work (such as COM objects, DLL's, etc).
I'd be interested in knowing if you've found a way round this.
Thanks
Try controlling the IIS pool with DirectoryEntry instead.
See this topic:
Check the status of an application pool (IIS 6) with C#
Microsoft.Web.Administration, it relies on System.Web.dll which was provided by framework 4, not client profile.

Categories