[英]Global.asax Application_Error equivalent in Startup.cs
[英]Is there any way to configure owin startup.cs to be run before global asax application start?
我正在嘗試在MVC 5中實現每個請求的容器和每個請求的事務模式。我已經利用全局asax編寫了大部分代碼。 我在創建多個上下文時遇到了麻煩,因為owin正在創建新的DbContext類作為startup.cs的一部分。 有什么辦法可以在全局asax應用程序啟動事件之前運行owin,以便可以檢索在那里創建的現有上下文? 我是這些模式的新手,因此,如果這個問題聽起來不正確,我歡迎您提出替代建議。
public IContainer Container
{
get
{
return (IContainer)HttpContext.Current.Items["_Container"];
}
set
{
HttpContext.Current.Items["_Container"] = value;
}
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
////Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
DependencyResolver.SetResolver(
new StructureMapDependencyResolver(() => Container ?? IoC.Container));
IoC.Container.Configure(cfg =>
{
cfg.AddRegistry(new StandardRegistry());
cfg.AddRegistry(new ControllerRegistry());
cfg.AddRegistry(new ActionFilterRegistry(
() => Container ?? IoC.Container));
cfg.AddRegistry(new MvcRegistry());
cfg.AddRegistry(new TaskRegistry());
cfg.AddRegistry(new ModelMetadataRegistry());
});
using (var container = IoC.Container.GetNestedContainer())
{
foreach (var task in container.GetAllInstances<IRunAtInit>())
{
task.Execute();
}
foreach (var task in container.GetAllInstances<IRunAtStartup>())
{
task.Execute();
}
}
}
public void Application_BeginRequest()
{
Container = IoC.Container.GetNestedContainer();
foreach (var task in Container.GetAllInstances<IRunOnEachRequest>())
{
task.Execute();
}
}
public void Application_Error()
{
foreach (var task in Container.GetAllInstances<IRunOnError>())
{
task.Execute();
}
}
public void Application_EndRequest()
{
try
{
foreach (var task in
Container.GetAllInstances<IRunAfterEachRequest>())
{
task.Execute();
}
}
finally
{
Container.Dispose();
Container = null;
}
}
結構圖類
public class StructureMapDependencyResolver : IDependencyResolver
{
private readonly Func<IContainer> _factory;
public StructureMapDependencyResolver(Func<IContainer> factory)
{
_factory = factory;
}
public object GetService(Type serviceType)
{
if (serviceType == null)
{
return null;
}
var factory = _factory();
return serviceType.IsAbstract || serviceType.IsInterface
? factory.TryGetInstance(serviceType)
: factory.GetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _factory().GetAllInstances(serviceType).Cast<object>();
}
Owin的啟動-在啟動和每個請求時在Global ASAX之后執行,但在全局ASAX代碼之后執行。 我希望能夠將OWIN上下文設置為現有的上下文實例,或者先執行此代碼並獲取在啟動時創建的上下文。
// For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
}
}
使用MVC 5,OWIN將始終在global.asax Application_Start()
之后運行。 這是因為MVC應用程序托管OWIN。 僅使用MVC注冊的App_Start,讓OWIN處理配置和啟動要容易得多。 因此,我建議將您的容器注冊和Startup
移動到Startup
。 像這樣:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
DependencyResolver.SetResolver(
new StructureMapDependencyResolver(IoC.Container));
IoC.Container.Configure(cfg =>
{
...
});
using (var container = IoC.Container.GetNestedContainer())
{
foreach (var task in container.GetAllInstances<IRunAtInit>())
{
task.Execute();
}
foreach (var task in container.GetAllInstances<IRunAtStartup>())
{
task.Execute();
}
}
}
}
然后,在Application_BeginRequest
, Application_EndRequest
和Application_Error
,您可以通過DependencyResolver訪問容器。 例如:
public void Application_BeginRequest()
{
foreach (var task in DependencyResolver.Current.GetServices<IRunOnEachRequest>())
{
task.Execute();
}
}
請注意,這里沒有更多的Container
屬性,並且隨后沒有嵌套的容器(啟動時除外)。 那是因為您的問題比管道計時更細微。 容器和按請求的事務模式實際上是關於生命周期 (特別是瞬態生命周期)的,在ASP.NET中,容器已經知道要解決每個請求。 因此,您無需重復這項工作。 StructureMap文檔比我能更好地解釋它。
旁注 :您可以在程序集中放置一個PreApplicationStart
屬性,該屬性指示在Application_start之前要運行哪種方法,但是由於它是靜態方法,因此它實際上僅對靜態配置有用-IoC容器不是。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.