Asp.net MVC4,PostgreSQL和SimpleMembership

时间:2014-03-21 05:01:55

标签: asp.net-mvc entity-framework postgresql

我使用Npgsql 2.1和EntityFramework 6.0来使用PostgreSQL(Code First)。 一切正常。这是我的Web.config的一部分:

<configuration>
  <configSections>
//---
  <connectionStrings>  
    <add name="MovieDBContext" connectionString="Server=127.0.0.1;Port=5432;Database=postgres;User Id=postgres;Password=123;" 
         providerName="Npgsql" />    
  </connectionStrings>
//---
  <entityFramework>
    <defaultConnectionFactory type="Npgsql.NpgsqlFactory, Npgsql" />
    <providers>
      <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql.EntityFramework"></provider>
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="Npgsql" />
      <add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql" 
type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
  </system.data>  
</configuration>

一切正常,10个相关表格。但现在我需要授权。

我当然读了这篇文章 PostgreSQL + Npgsql connector + MVC and SimpleMembership Not working Francisco Junior建议使用Daniel Nauck的AspSQLProvider。

我从NuGet安装了NauckIT.PostgreSQLProvider.2.0.0。 从包中执行脚本以为其创建表集。 将此部分配置信息添加到Web.config:

 <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>

    <machineKey validationKey="518A9D0E650ACE4CB22A35DA4563315098A96D0BB8E357531C7065D032099214A11D1CA074B6D66FF0836B35CEAAD0E7EEEFAED772754832E0A5F94EF8522222"
        decryptionKey="DB5660C109E9EC70F044BA1FED99DE0C5922321C5125E84C23A1B5CA0E426909"
        validation="SHA1" decryption="AES" />

    <membership defaultProvider="PgMembershipProvider">
      <providers>
        <clear/>
        <add name="PgMembershipProvider" type="NauckIT.PostgreSQLProvider.PgMembershipProvider" connectionStringName="MovieDBContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" passwordFormat="Hashed" applicationName="MvcMovie"/>
      </providers>
    </membership>

    <roleManager enabled="true" defaultProvider="PgRoleProvider" cacheRolesInCookie="true" cookieName=".AspNetRoles" cookiePath="/" cookieProtection="All" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="false" cookieTimeout="30" maxCachedResults="25">
      <providers>
        <clear/>
        <add name="PgRoleProvider" type="NauckIT.PostgreSQLProvider.PgRoleProvider" connectionStringName="MovieDBContext" applicationName="MvcMovie"/>
      </providers>
    </roleManager>

    <profile enabled="true" defaultProvider="PgProfileProvider">
      <providers>
        <clear/>
        <add name="PgProfileProvider" type="NauckIT.PostgreSQLProvider.PgProfileProvider" connectionStringName="MovieDBContext" applicationName="MvcMovie"/>
      </providers>
      <properties>
        <add name="FirstName"/>
        <add name="LastName"/>
      </properties>
    </profile>

    <sessionState    mode="Custom"    customProvider="PgSessionStateStoreProvider">
      <providers>
        <clear/>
        <add name="PgSessionStateStoreProvider" type="NauckIT.PostgreSQLProvider.PgSessionStateStoreProvider" enableExpiredSessionAutoDeletion="true" expiredSessionAutoDeletionInterval="60000" enableSessionExpireCallback="false" connectionStringName="MovieDBContext" applicationName="MvcMovie" />
      </providers>
    </sessionState>

尝试运行时出错:

Parser Error Message: This method cannot be called during the application's pre-start initialization phase.
Source Error: 
<providers>
<clear/>
<add name="PgMembershipProvider" type="NauckIT.PostgreSQLProvider.PgMembershipProvider" connectionStringName="MovieDBContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" passwordFormat="Hashed" applicationName="MvcMovie"/>
</providers>
</membership>

试图找到有关此错误的任何内容。 遵循此建议 asp.net 4.5 custom membership provider configuration throws strange exception 我将其添加到Web.config

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

现在应用程序可以运行,因为SimpleMembership已被禁用。 顺便说一句,尝试注册用户我得到下一个错误

System.Reflection.TargetInvocationException was unhandled by user code
  HResult=-2146232828
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
       at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
       at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
       at System.Activator.CreateInstance(Type type, Boolean nonPublic)
       at System.Activator.CreateInstance(Type type)
       at System.Threading.LazyHelpers`1.ActivatorFactorySelector()
       at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory)
       at System.Threading.LazyInitializer.EnsureInitialized[T](T& target, Boolean& initialized, Object& syncLock)
       at MvcMovie.Filters.InitializeSimpleMembershipAttribute.OnActionExecuting(ActionExecutingContext filterContext) in d:\Projects\_Npg\MvcMovieSln\MvcMovie\Filters\InitializeSimpleMembershipAttribute.cs:line 22
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain)
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35()
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain)
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588
       Source=MvcMovie
       StackTrace:
            at MvcMovie.Filters.InitializeSimpleMembershipAttribute.SimpleMembershipInitializer..ctor() in d:\Projects\_Npg\MvcMovieSln\MvcMovie\Filters\InitializeSimpleMembershipAttribute.cs:line 46
       InnerException: System.InvalidOperationException
            HResult=-2146233079
            Message=Failed to set Database.DefaultConnectionFactory to an instance of the 'Npgsql.NpgsqlFactory, Npgsql' type as specified in the application configuration. See inner exception for details.
            Source=EntityFramework
            StackTrace:
                 at System.Data.Entity.Internal.AppConfig.<.ctor>b__3()
                 at System.Lazy`1.CreateValue()
                 at System.Lazy`1.LazyInitValue()
                 at System.Lazy`1.get_Value()
                 at System.Data.Entity.Internal.AppConfig.TryGetDefaultConnectionFactory()
                 at System.Data.Entity.Infrastructure.DependencyResolution.AppConfigDependencyResolver.GetServiceFactory(Type type, String name)
                 at System.Data.Entity.Infrastructure.DependencyResolution.AppConfigDependencyResolver.<>c__DisplayClass1.<GetService>b__0(Tuple`2 t)
                 at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
                 at System.Data.Entity.Infrastructure.DependencyResolution.AppConfigDependencyResolver.GetService(Type type, Object key)
                 at System.Data.Entity.Infrastructure.DependencyResolution.ResolverChain.<>c__DisplayClass3.<GetService>b__0(IDbDependencyResolver r)
                 at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
                 at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
                 at System.Data.Entity.Infrastructure.DependencyResolution.ResolverChain.GetService(Type type, Object key)
                 at System.Data.Entity.Infrastructure.DependencyResolution.CompositeResolver`2.GetService(Type type, Object key)
                 at System.Data.Entity.Infrastructure.DependencyResolution.DbDependencyResolverExtensions.GetService[T](IDbDependencyResolver resolver)
                 at System.Data.Entity.Internal.LazyInternalConnection.Initialize()
                 at System.Data.Entity.Internal.LazyInternalConnection.get_ProviderName()
                 at System.Data.Entity.Internal.LazyInternalContext.get_ProviderName()
                 at System.Data.Entity.Internal.DefaultModelCacheKeyFactory.Create(DbContext context)
                 at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
                 at System.Data.Entity.Internal.InternalContext.CreateObjectContextForDdlOps()
                 at System.Data.Entity.Database.Exists()
                 at MvcMovie.Filters.InitializeSimpleMembershipAttribute.SimpleMembershipInitializer..ctor() in d:\Projects\_Npg\MvcMovieSln\MvcMovie\Filters\InitializeSimpleMembershipAttribute.cs:line 35
            InnerException: System.MissingMethodException
                 HResult=-2146233069
                 Message=Constructor on type 'Npgsql.NpgsqlFactory' not found.
                 Source=mscorlib
                 StackTrace:
                      at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
                      at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
                      at System.Activator.CreateInstance(Type type, Object[] args)
                      at System.Data.Entity.Internal.AppConfig.<.ctor>b__3()
                 InnerException: 

中的

LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);

在班级

InitializeSimpleMembershipAttribute

请帮助配置Daniel Nauck的AspSQLProvider和InitializeSimpleMembershipAttribute(如果需要)。

谢谢!

1 个答案:

答案 0 :(得分:3)

问题在于实现AccountController而不是默认。

确定。这是解决方案

我喜欢PostgreSQL的会员和角色提供者 https://code.google.com/p/pgprovider/ 因为它在启动时自己创建所有必要的表))

安装它:

Install-Package pgProvider

添加到Web.config:

  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <connectionStrings>
    <add name="MovieDBContext" connectionString="Server=127.0.0.1;Port=5432;Database=postgres;User Id=postgres;Password=000;" providerName="Npgsql" />
    <add name="pgProvider" connectionString="Server=127.0.0.1;Port=5432;Database=postgres;User Id=postgres;Password=000;" providerName="Npgsql" />    
  </connectionStrings>

    <membership defaultProvider="pgMembershipProvider">
      <providers>
        <clear />
        <add name="pgMembershipProvider" type="pgProvider.pgMembershipProvider, pgProvider" applicationName="MvcMovie"/>
      </providers>
    </membership>
    <roleManager defaultProvider="pgRoleProvider">
      <providers>
        <clear />
        <add name="pgRoleProvider" type="pgProvider.pgRoleProvider, pgProvider" applicationName="MvcMovie"/>
      </providers>
    </roleManager>

然后添加到Web.config:

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

然后删除默认创建的AccountController。

最后添加AccountController:

public class AccountController : Controller 
{
    public ActionResult Login(string returnUrl)
    {
        ViewBag.ReturnUrl = returnUrl;        
        return View();
    }

[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }
    return View(model);
}

public ActionResult LogOff()
{
    FormsAuthentication.SignOut();

    return RedirectToAction("Login", "Account");
}

public ActionResult Register()
{
    return View();
}

[HttpPost]
public ActionResult Register(RegisterModel model)
{           
    if (ModelState.IsValid)
    {
        MembershipCreateStatus status;

        MembershipUser membershipUser = (Membership.Provider).CreateUser(
            model.UserName, model.Password, null,null,null, true, null, out status);

        if (membershipUser != null)
        {
            FormsAuthentication.SetAuthCookie(model.UserName, false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            ModelState.AddModelError("", "Registration error");
        }
    }
    return View(model);
}

}

提供商的源代码在这里: https://code.google.com/p/pgprovider/source/browse/trunk/pgProvider/pgMembershipProvider.cs

就是这样。

它适用于默认创建的登录和注册视图。