Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SqlRoleProvider on IIS8 Express

My web application (a WCF service) uses SqlRoleProvider, which works fine on Visual Studio Development Server. Switching it to IIS8 Express causes it to throw a NullReferenceException though:

Roles.IsUserInRole(username, role) // neither of them actually null

I could not find a hint for this exception in the IsUserInRole method documentation. Switching back to Visual Studio Development server makes it work. What is the cause of this exception, and how could I fix it properly? The project's target framework is .NET Framework 4.

Here is the configured connection string:

<add name="ConnectionString"
      connectionString="Data Source=.\sqlexpress;Initial Catalog=DevWeb;Integrated Security=True"
      providerName="System.Data.SqlClient" />

And this is the roleManager/providersnode:

<clear />
<add connectionStringName="ConnectionString" applicationName="MyApp" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider"/>
like image 600
Matthias Meid Avatar asked Jan 28 '26 01:01

Matthias Meid


2 Answers

What Vladimir said is true but doesn't actually explain what is happening. What throws the NullReferenceException is the EtwTrace code that's in IsUserInRole and GetRolesForUser. Everything else in the Roles class accounts for the fact that HttpContext.Current can be null. I found this by looking in the Microsoft Reference Source for "NET, Version 4.5" at http://referencesource.microsoft.com/netframework.aspx

In every other test environment I tried, the tracing level was not sufficient to trigger the NullReferenceException. It was only when I used IIS Express 8 after installing Visual Studio 2013 that I saw the issue and only in IIS Express.

What can you do about it?

One option is to enable "ASP.Net Compatibility Mode" for WCF. First, in the web.config, add the attribute aspNetCompatibilityEnabled="true" to the node <configuration><system.serviceModel><serviceHostingEnvironment>. Then opt your service class into the behavior by adding the attribute [System.ServiceModel.Activation.AspNetCompatibilityRequirements(RequirementsMode = System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)] to the class definition.With this functionality enabled, HttpContext.Current will be populated by the time you go to request roles from the Roles class, assuming you're not working on a background thread like Vladimir mentioned (in which case you'll need to patch up the HttpContext.Current first). You can read more about ASP.NET Compatibility Mode for WCF at http://blogs.msdn.com/b/wenlong/archive/2006/01/23/516041.aspx.

The other option is to bypass the Roles class for these two methods. Instead of calling Roles.IsUserInRole, call Roles.Provider.IsUserInRole. Instead of calling Roles.GetRolesForUser, call Roles.Provider.GetRolesForUser. Each method has the same overloads available. You lose the trace stops and the local role cache but you bypass the null reference exception.

like image 130
Programmerman Avatar answered Jan 30 '26 15:01

Programmerman


If you calling Roles.IsUserInRole in different Thread then you should check HttpContext. In this case will be empty. So, for fix you should copy HttpContext from main thread to child thread.

        var context = HttpContext.Current;
        Thread thread = new Thread(delegate() {
            if (HttpContext.Current == null)
                HttpContext.Current = context;
        });

        thread.Start();
like image 39
Vladimir Avatar answered Jan 30 '26 14:01

Vladimir



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!