Search code examples
asp.net-mvc-4razoruser-rolesasp.net-roles

IsUserInRole method is not working properly


Following 'if' condition is not working i.e. Roles.IsUserInRole(User.Identity.Name,"teacher") is not returning anything (it is returning zero). what should I do to make it work? Requirement is to display different pages to users register as teacher and different pages to users register as student.

@if (Request.IsAuthenticated && Roles.IsUserInRole(User.Identity.Name,"teacher"))//HttpContext.Current.User.IsInRole("teacher"))//User.IsInRole("teacher")) //Roles.IsUserInRole(User.Identity.Name,"teacher"))
            {


            <li>@Html.ActionLink("Quiz Management", "Index", "Quiz")</li>                       
            <li>@Html.ActionLink("Browse Quizzes", "Index", "TakeQuiz")</li>
            <li>@Html.ActionLink("Assignment Scheduling", "Index", "Assignment")</li>

        }

This is my register action method in account controller:

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    var vRole = Request["selectRole"];
                   // WebSecurity.InitializeDatabaseConnection();
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
                    WebSecurity.Login(model.UserName, model.Password);
                    if (vRole.Equals("teacher"))
                    {
                        Roles.AddUserToRole(model.UserName, "teacher");//AddUserToRole(model.UserName, "teacher");
                    }
                    else
                    {
                        Roles.AddUserToRole(model.UserName, "student");
                    }
                    return RedirectToAction("Index", "Home");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

Here is Web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth.Core">
      <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" />
      <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" />
      <section name="openid" type="DotNetOpenAuth.Configuration.OpenIdElement, DotNetOpenAuth.OpenId" requirePermission="false" allowLocation="true" />
      <section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth.OAuth" requirePermission="false" allowLocation="true" />
    </sectionGroup>
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=mydb;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\mydb.mdf;" providerName="System.Data.SqlClient" />
    <add name="mydbEntities" connectionString="metadata=res://*/Models.mymodel.csdl|res://*/Models.mymodel.ssdl|res://*/Models.mymodel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDb)\v11.0;attachdbfilename=|DataDirectory|\mydb.mdf;initial catalog=mydb;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    <add name="mydbEntities1" connectionString="metadata=res://*/Models.mymodel.csdl|res://*/Models.mymodel.ssdl|res://*/Models.mymodel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDb)\v11.0;attachdbfilename=|DataDirectory|\mydb.mdf;initial catalog=mydb;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <!--i have made new version from 2.0.0.0 to 3-->
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.AspNet" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
        <!--i have made new version from 2.0.0.0 to 3-->
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System" publicKeyToken="b77a5c561934e089" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
      </dependentAssembly>
    </assemblyBinding>
    <!--This prevents the Windows Event Log from frequently logging that HMAC1 is being used (when the other party needs it). <legacyHMACWarning enabled="0" /> When targeting ASP.NET MVC 3, this assemblyBinding makes MVC 1 and 2 references relink
             to MVC 3 so libraries such as DotNetOpenAuth that compile against MVC 1 will work with it.-->
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.net>
    <defaultProxy enabled="true" />
    <settings>
      <!--This setting causes .NET to check certificate revocation lists (CRL) 
                 before trusting HTTPS certificates.  But this setting tends to not 
                 be allowed in shared hosting environments.-->
      <servicePointManager checkCertificateRevocationList="true" />
    </settings>
  </system.net>
  <dotNetOpenAuth>
    <messaging>
      <untrustedWebRequest>
        <whitelistHosts>
          <!--Uncomment to enable communication with localhost (should generally not activate in production!)-->
          <add name="localhost" />
        </whitelistHosts>
      </untrustedWebRequest>
    </messaging>
    <!--Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library.-->
    <!--<reporting enabled="true" />-->
    <!--This is an optional configuration section where aspects of dotnetopenauth can be customized.  For a complete set of configuration options see http://www.dotnetopenauth.net/developers/code-snippets/configuration-options/-->
    <openid>
      <relyingParty>
        <security requireSsl="false">
                     Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. 
                    <trustedProviders rejectAssertionsFromUntrustedProviders="true"><add endpoint="https://www.google.com/accounts/o8/ud" /></trustedProviders></security>
        <behaviors>
          <!--The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
                         with OPs that use Attribute Exchange (in various formats).-->
          <add type="DotNetOpenAuth.OpenId.RelyingParty.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth.OpenId.RelyingParty" />
        </behaviors>
      </relyingParty>
    </openid>
  </dotNetOpenAuth>
  <uri>
    <!--The uri section is necessary to turn on .NET 3.5 support for IDN (international domain names),
             which is necessary for OpenID urls with unicode characters in the domain/host name.
             It is also required to put the Uri class into RFC 3986 escaping mode, which OpenID and OAuth require.-->
    <idn enabled="All" />
    <iriParsing enabled="true" />
  </uri>
</configuration>

I think I am missing something? What should I do to fix it ? Regards.


Solution

  • https://msdn.microsoft.com/en-us/library/ff647070.aspx

    The FormsAuthenticationModule class constructs a GenericPrincipal object and stores it in the HTTP context. The GenericPrincipal object holds a reference to a FormsIdentity instance that represents the currently authenticated user. You should allow forms authentication to manage these tasks for you. If your applications have specific requirements, such as setting the User property to a custom class that implements the IPrincipal interface, your application should handle the PostAuthenticate event. The PostAuthenticate event occurs after the FormsAuthenticationModule has verified the forms authentication cookie and created the GenericPrincipal and FormsIdentity objects. Within this code, you can construct a custom IPrincipal object that wraps the FormsIdentity object, and then store it in the HttpContext.User property.

    In other words, you need to create new GenericPrincial in the overridden Application_PostAuthenticateRequest method (see Global.asax). Something like this:

    protected void Application_PostAuthenticateRequst(object sender, EventArgs e)
    {
        if (Context.User.Identity.IsAuthenticated
         && Context.User.Identity.AuthenticationType == "Forms")
        {
            // You should get roles in the user by his UserName:
            // string[] roles = ...
            // With Role provider it will look like
            var roles = Roles.GetRolesForUser(Context.User.Identity.Name);
    
            Context.User = new GenericPrincipal(Context.User.Identity, roles);
            Thread.CurrentPrincipal = Context.User;
        }
    }