web-dev-qa-db-fra.com

La configuration du fournisseur d'adhésion personnalisé asp.net 4.5 lève une étrange exception

Mon site Web a été initialement écrit en MVC 4.0 RC en utilisant VS2010,. Je viens de télécharger et d'installer VS2012 et de mettre à niveau mon projet vers Dotnet Framework 4.5.

Dans mon projet, j'utilise un MemberShipProvider personnalisé et un RoleProvider personnalisé. Sur VS2010, cela a fonctionné comme un charme. Mais maintenant, je continue d'obtenir une étrange erreur de configuration:

"Cette méthode ne peut pas être appelée pendant la phase d'initialisation préalable au démarrage de l'application."

La ligne "system.web -> membership -> providers -> add" dans mon web.config est marquée en rouge comme source du problème.

J'ai éliminé le soupçon que le problème a quelque chose à voir avec le processus de migration, en créant un nouveau projet MVC 4.0 (dans VS2012), en ajoutant mes fournisseurs d'appartenance/de rôle personnalisés, en modifiant le fichier web.config de manière appropriée et en constatant que l'erreur réapparaît!

Pour approfondir le problème, j'ai trouvé les informations suivantes dans le journal des applications:

Informations sur l'exception: Type d'exception: InvalidOperationException Message d'exception: La méthode d'initialisation de démarrage de pré-application Le type WebMatrix.WebData.PreApplicationStartCode a généré une exception avec le message d'erreur suivant: Cette méthode ne peut pas être appelée pendant la phase d'initialisation de pré-démarrage de l'application. (C:\Users\dov.AD\Documents\Visual Studio 2012\Projects\MvcApplication2\MvcApplication2\web.config ligne 52).
sur System.Web.Compilation.BuildManager.InvokePreStartInitMethodsCore (ICollection1 methods, Func1 setHostingEnvironmentCultures) sur System.Web.Compilation.BuildManager.InvokePreStartInitMethods (ICollection`SystemCompilation System.Web.Compilation.BuildManager.ExecutePreAppStart () sur System.Web.Hosting.HostingEnvironment.Initialize (ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters, policyParamel, exceptionParamel

Cette méthode ne peut pas être appelée pendant la phase d'initialisation préalable au démarrage de l'application. (C:\Users\dov.AD\Documents\Visual Studio 2012\Projects\MvcApplication2\MvcApplication2\web.config ligne 52)
sur System.Web.Configuration.ConfigUtil.GetType (String typeName, String propertyName, ConfigurationElement configElement, nœud XmlNode, Boolean checkAptcaBit, Boolean ignoreCase) sur System.Web.Configuration.ConfigUtil.GetType (String typeName , ConfigurationElement configElement, Boolean checkAptcaBit, Boolean ignoreCase) chez System.Web.Configuration.ProvidersHelper.InstantiateProvider (ProviderSettings providerSettings, Type providerType) chez System.Web.Configuration.ProvidersHelper.InstantiateProvidersConfigurationConfirmers, ProviderSettypeCollider Provider Provider,
sur System.Web.Security.Membership.InitializeSettings (Boolean initializeGeneralSettings, RuntimeConfig appConfig, MembershipSection settings) sur System.Web.Security.Membership.Initialize () sur System.Web.Security.Membership.get_Providers () sur WebMatrix.WebData.WebSecurity.PreAppStartInit () sur WebMatrix.WebData.PreApplicationStartCode.Start ()

Cette méthode ne peut pas être appelée pendant la phase d'initialisation préalable au démarrage de l'application. à System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled ()
sur System.Web.Compilation.BuildManager.GetType (String typeName, Boolean throwOnError, Boolean ignoreCase) sur System.Web.Configuration.ConfigUtil.GetType (String typeName, String propertyName, ConfigurationElement configElement, nœud XmlAnode, Boolean , Boolean ignoreCase)

Request information: 
Request URL: http://localhost:4995/ 
Request path: / 
User Host address: ::1 
User:  
Is authenticated: False 
Authentication Type:  
Thread account name: AD\dov    Thread information: 
Thread ID: 5 
Thread account name: AD\dov 
Is impersonating: False 
Stack trace:    at >System.Web.Compilation.BuildManager.InvokePreStartInitMethodsCore(ICollection`1

méthodes Func1 setHostingEnvironmentCultures) at System.Web.Compilation.BuildManager.InvokePreStartInitMethods(ICollection 1) à System.Web.Compilation.BuildManager.CallPreStartInitMethods (String preStartInitListPath) à System.Web.Compilation.BuildManager.ExecutePreAppStart () à System.Web.Hosting.HostingEnvironment Application (System.Web.Hosting.HostingEnvironment Application) , IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException)

Veuillez aider,

Je vous remercie!

Voici le web.config:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.Microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.Microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MyWebSite-20120820105950;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MyWebSite-20120820105950.mdf" providerName="System.Data.SqlClient" />
    <add name="MyWebSiteDbContext" providerName="System.Data.SqlClient" connectionString="server=.;database=MyWebSiteDB;Integrated Security=True;" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <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>
    <profile>
      <providers>
        <clear/>
      </providers>
    </profile>
    <roleManager defaultProvider="MyWebSiteRoleProvider" enabled="true">
      <providers>
        <clear/>     
        <add name="MyWebSiteRoleProvider" type="MyWebSite.Security.MyWebSiteRoleProvider"/>
      </providers>
    </roleManager>
    <membership defaultProvider="MyWebSiteMembershipProvider">
      <providers>
        <clear />
        <add name="MyWebSiteMembershipProvider" type="MyWebSite.Security.MyWebSiteMembershipProvider"  />
      </providers>
    </membership>
  </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="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.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>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
</configuration>

Il s'agit de l'appartenance personnalisée pertinente (je l'ai simplifiée, mais même si le problème persiste), seul ValidateUser est vraiment remplacé:

using System;
using System.Linq;
using System.Web.Security;
using DAL.MyWebSite;

namespace MyWebSite.Security
{
    public class MyWebSiteMembershipProvider : MembershipProvider
    {




        /// <summary>
        /// Verifies that the specified user name and password exist in the data source.
        /// </summary>
        /// <returns>
        /// true if the specified username and password are valid; otherwise, false.
        /// </returns>
        /// <param name="username">The name of the user to validate. </param><param name="password">The password for the specified user. </param>
        public override bool ValidateUser(string username, string password)
        {
            // simplified
            return true;
        }



    }
}

Voici le fournisseur de rôles (simplifié):

using System;
using System.Linq;
using System.Web.Security;
using DAL.MyWebSite;

namespace MyWebSite.Security
{
    public class MyWebSiteRoleProvider : RoleProvider
    {


        //readonly MyWebSiteDbContext _context = new MyWebSiteDbContext();
        /// <summary>
        /// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
        /// </summary>
        /// <returns>
        /// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
        /// </returns>
        /// <param name="username">The user name to search for.</param><param name="roleName">The role to search in.</param>
        public override bool IsUserInRole(string username, string roleName)
        {
            return true;
            //return GetRolesForUser(username).Contains(roleName);
        }

        /// <summary>
        /// Gets a list of the roles that a specified user is in for the configured applicationName.
        /// </summary>
        /// <returns>
        /// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
        /// </returns>
        /// <param name="username">The user to return a list of roles for.</param>
        public override string[] GetRolesForUser(string username)
        {
            return new string[] {"one", "two"};

            //var sm = _context.SalesManagers.Include("PermissionLevel").FirstOrDefault(manager => manager.UserName == username);

            //if (sm != null)
            //{
            //    if (sm.PermissionLevel.Name == "Sales Manager")
            //    {
            //        return new[] { "SalesManagers" };
            //    }

            //    if (sm.PermissionLevel.Name == "Administrator")
            //    {
            //        return new[] { "SalesManagers", "Administrators" };
            //    }

            //} 
            //return null;

        }

    }
}
30
berke762

J'utilise mes propres fournisseurs d'adhésion et de rôle personnalisés dans Depuis MVC2 et j'ai rencontré ce problème lorsque j'ai migré de MVC3 vers 4.

J'ai créé un nouveau projet dans MVC4/.net4.5 EF5 et j'ai eu la chance de rencontrer cette erreur.

J'ai réussi à le réparer en procédant comme suit:

Ajoutez ceci à vos paramètres d'application de configuration Web:

  <appSettings>
    <add key="enableSimpleMembership" value="false"/>
    <add key="autoFormsAuthentication" value="false"/>
  </appSettings>

Ajoutez votre chaîne de connexion à vos abonnements et fournisseurs de rôles s'ils ne sont pas déjà définis:

<membership defaultProvider="MyMembershipProvider">
  <providers>
    <add name="MyMembershipProvider" type="AMS.WebUI.Infrastructure.CustomMembershipProvider" connectionStringName="EFDbContext" />
  </providers>
</membership>
<roleManager defaultProvider="MyRoleprovider">
  <providers>
    <add name="MyRoleprovider" type="AMS.WebUI.Infrastructure.CustomRoleProvider" connectionStringName="EFDbContext" />
  </providers>
</roleManager>

Cela a résolu le problème pour moi et j'espère que cela peut vous aider.

70
Ben Pretorius

OK, voyons si je peux expliquer cela correctement. ASP.NET 4 a introduit un nouvel attribut au niveau de l'assembly: PreApplicationStartMethodAttribute, qui est généralement utilisé dans le fichier Properties/AssemblyInfo.cs.

Le modèle standard ASP.NET MVC 4 est fourni avec une référence à l'assembly WebMatrix.WebData. En regardant son code , le AssemblyInfo a ceci:

[Assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")]

Donc, fondamentalement, avant même que App_Start soit appelé, le framework appellera WebMatrix.WebData.PreApplicationStartCode.Start() qui, entre autres, fait cela

// Initialize membership provider
WebSecurity.PreAppStartInit();

Et bien sûr, comme @Ben Pretorius l'a dit, cette méthode commence comme ça

internal static void PreAppStartInit()
{
    // Allow use of <add key="EnableSimpleMembershipKey" value="false" /> to disable registration of membership/role providers as default.
    if (ConfigUtil.SimpleMembershipEnabled)
    {
        ...

Donc, vous avez comment/pourquoi cela échoue "automatiquement". C'est vraiment dommage que Microsoft n'ait pas inclus <add key="EnableSimpleMembershipKey" value="true" /> Dans le Web.config standard pour rendre plus évident que "hé il y a ce truc SimpleProvider qui est configuré ici".

24
Oli

Je jouais aussi un peu autour de cela et regardais le code WebMatrix et finalement je pense que la solution de Ben semble être celle qui fonctionne.

(J'ai également essayé de jouer avec les références de l'assembly sans succès. Je pense qu'en supprimant les références que vous venez d'obtenir, tout comme les paramètres de configuration, la sécurité WebMatrix n'a pas été correctement initialisée. Mais je pense que c'est assez dangereux. Mais Je devine juste ici.)

Donc pour moi ce qui a fonctionné:

<appSettings>
  <add key="enableSimpleMembership" value="false"/>
</appSettings>

<membership defaultProvider="MyMembershipProvider">
  <providers>
    <clear />
    <add name="MyMembershipProvider" type="MyNamespace.MyMembershipProvider" />
  </providers>
</membership>
<!-- this role configuration below uses the SimpleRoleProvider, because I just 
     wanted to replace the membership provider. If you need to replace that one 
     too, just use your own class instead. -->
<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">
  <providers>
    <remove name="AspNetSqlRoleProvider" />
    <add name="AspNetSqlRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <!-- note: WebMatrix registers SimpleRoleProvider with name
         'AspNetSqlRoleProvider'. I don't know why but i kept it. -->
  </providers>
</roleManager>

J'ai vérifié le code WebMatrix, et il semble que la définition de "enableSimpleMembership" sur false soit assez inoffensive. WebMatrix ne l'utilise que pour initialiser les fournisseurs d'appartenance/de rôle (qui peuvent être remplacés par la configuration ci-dessus) et il active l'authentification par formulaires permettant une configuration alternative (via les paramètres de l'application) - cela n'est également pas nécessaire, si vous avez les formulaires standard authentification correctement configurée (principalement "loginUrl" est le seul acteur important ici).

J'ai également essayé de vérifier ce que fait le paramètre 'autoFormsAuthentication' - mais je n'ai rien trouvé, alors je l'ai simplement sauté. Ça a l'air bien encore.

8
Gaspar Nagy

J'ai déjà résolu le problème. J'ai trouvé que lorsque vous créez un projet MVC 4 dans VS2012, le modèle ajoute des références à certains assemblages, parmi eux: webmatrix et Oauth ... Je viens de supprimer ces références et le problème a disparu. Je ne sais pas comment cela a résolu le problème, mais j'ai vu que l'exception provenait de WebMatrix Assembly, c'est pourquoi j'ai essayé de la supprimer. Désolé, mais je n'ai pas le temps d'investir dans l'enquête ....

2
berke762