Asp.net mvc 为什么在MVC4应用程序中初始化SimpleMembershipAttribute
我认为我对SimpleMembershipProvider的理解几乎是60%,其他人正在了解它的内部工作原理 仅在AccountController(默认模板)中使用Asp.net mvc 为什么在MVC4应用程序中初始化SimpleMembershipAttribute,asp.net-mvc,asp.net-mvc-4,simplemembership,Asp.net Mvc,Asp.net Mvc 4,Simplemembership,我认为我对SimpleMembershipProvider的理解几乎是60%,其他人正在了解它的内部工作原理 仅在AccountController(默认模板)中使用[InitializeSimpleMembership]过滤器时,您会很快发现一些问题。我认为无论您在哪里使用Memberhsip API或WebMatrix.WebSecurity,都需要确保首先调用此筛选器 稍后,如果在我的\u Layout.cshtml中使用User.IsInRole。您需要将筛选器应用于所有控制器,然后开始
[InitializeSimpleMembership]
过滤器时,您会很快发现一些问题。我认为无论您在哪里使用Memberhsip API或WebMatrix.WebSecurity
,都需要确保首先调用此筛选器
稍后,如果在我的\u Layout.cshtml
中使用User.IsInRole
。您需要将筛选器应用于所有控制器,然后开始在全局中注册它
然而,我刚刚意识到有一个LazyInitializer.EnsureInitialized
,它使得每次应用程序启动只执行一次初始化
那么为什么SimpleMembershipInitializer
(在过滤器中)不直接在应用程序启动中呢?
是否有任何理由使用过滤器?我相信模板使用了一个属性进行数据库初始化,这样,如果初始化失败,站点的未经验证部分仍然可以工作
出于最实际的目的,最好在App_Start中完成此操作。我花了一天的时间试图找出我的角色.getrolefourser失败的原因。这是因为懒散的初始化器没有被调用
就像马特说的,只要把它放在App_Start中,确保没有问题。如果要将
初始化SimpleMembershipAttribute
合并到全局.asax.cs
应用程序_Start
中,那么SimpleMembershipProvider
将在不调用任何AccountController
路由的情况下进行初始化
…它可能看起来像这样:
//下面的用法是“UsersContext”所必需的-它将与您的项目名称空间相关
使用mvcapapplication1.模型;
使用制度;
使用System.Data.Entity;
使用System.Data.Entity.Infrastructure;
使用系统线程;
使用System.Web.Http;
使用System.Web.Mvc;
使用System.Web.Optimization;
使用System.Web.Routing;
使用WebMatrix.WebData;
命名空间MVCAPApplication1
{
//注:有关启用IIS6或IIS7经典模式的说明,
//拜访http://go.microsoft.com/?LinkId=9394801
公共类MVC应用程序:System.Web.HttpApplication
{
受保护的无效应用程序\u Start()
{
RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
//确保每次应用程序启动仅初始化一次ASP.NET简单成员身份
LazyInitializer.确保重新初始化(参考初始值设定项,参考初始值设定项,参考初始值设定项锁定);
}
私有静态SimpleMembershipInitializer\u initializer;
私有静态对象_initializerLock=新对象();
私有静态布尔值初始化;
私有类SimpleMembershipInitializer
{
公共SimpleMembershipInitializer()
{
Database.SetInitializer(null);
尝试
{
使用(var context=new UsersContext())
{
如果(!context.Database.Exists())
{
//创建没有实体框架迁移模式的SimpleMembership数据库
((IObjectContextAdapter)context.ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection(“DefaultConnection”、“UserProfile”、“UserId”、“UserName”,autoCreateTables:true);
}
捕获(例外情况除外)
{
抛出新的InvalidOperationException(“无法初始化ASP.NET简单成员身份数据库。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=256588“,ex);
}
}
}
}
}
InitializeSimpleMembership筛选器及其过于复杂的代码的原因是,当开发人员可能决定不使用表单身份验证时,模板生成的代码仍能正常工作。如果始终使用表单身份验证,则可以在Global.asax的Application\u Start方法中初始化SimpleMembership。有。如果计划确保InitializeSimpleMembership属性
在全球范围内运行,最好在应用程序启动\FilterConfig.cs中使用MVC 4方式
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new InitializeMembershipAttribute());
}
}
保持Global.asax.cs与可能应该像MVC4与以前版本一样封装的代码保持一致。留下一个干净漂亮的房间:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
我还建议将类型更改为AuthorizeAttribute(实际上就是这样做的),因为AuthorizeAttribute方法是在ActionFilterAttribute方法之前执行的。(如果其他ActionFilter正在检查安全性,并且允许派生的自定义属性,那么这应该会产生较少的问题)
我在这个问题上花了很多时间。但我最后只做了这样的改变:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new InitializeSimpleMembershipAttribute());
}
}
我随机看到了以下错误
System.Web.HttpException(0x80004005):无法连接到SQL Server数据库。-->System.Data.SqlClient.SqlException(0x80131904):建立到SQL Server的连接时发生与网络相关或特定于实例的错误。找不到服务器或无法访问服务器。验证实例名称是否正确,以及SQL Server是否配置为允许远程连接。(提供程序:SQL网络接口,错误:26-定位指定的服务器/实例时出错)
我注意到,每当我看到错误时,我也会看到:
在ASP
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Method,
AllowMultiple = false,
Inherited = true)]
public class InitializeMembershipAttribute : AuthorizeAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnAuthorization(AuthorizationContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer,
ref _isInitialized,
ref _initializerLock);
base.OnAuthorization(filterContext);
}
private class SimpleMembershipInitializer ...
}
}
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new InitializeSimpleMembershipAttribute());
}
}
if (User != null && User.Identity != null && (User.IsInRole("publisher") || User.IsInRole("admin")))
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<DataContext>(null);
@{
var maintenanceAccess = false;
if (User != null && User.Identity != null && (User.IsInRole("publisher") || User.IsInRole("admin")))
{
maintenanceAccess = true;
}
}
filters.Add(new InitializeSimpleMembershipAttribute());
public InitializeSimpleMembershipAttribute()
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public InitializeSimpleMembershipAttribute()
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
//public override void OnActionExecuting(ActionExecutingContext filterContext)
//{
// // Ensure ASP.NET Simple Membership is initialized only once per app start
// LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
//}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("Database_Connection_String_Name", "Users", "UserId", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}