使用 ASP.NET MVC 时将 Global.asax 移至 iHttpModule
我已经成功创建了一个 iHttpModule 来替换许多 Web 窗体应用程序中的 Global.asax 文件。但在我的 MVC 应用程序中查看 Global.asax 文件时,方法完全不同。
我想知道是否仍然可以在 MVC 应用程序中创建同样的东西。我知道这是没有必要的,Global.asax 工作得很好。我想我只想在应用程序的根目录中只保留 web.config 。
另外,我将所有类放在单独的类库项目中,而不是放在 MVC 应用程序中的文件夹中。不确定这是否有影响。
这是我目前所拥有的,但不幸的是我的路线没有注册
MVCApplication.vb (Class)
Imports System.Web.Mvc
Imports System.Web.Routing
Imports System.Web
Imports System.Text.RegularExpressions
Public Class MvcApplication : Inherits System.Web.HttpApplication : Implements IHttpModule
#Region "Global Variables/Objects"
Private UrlRegex As New Regex("(http|https)://www\.", RegexOptions.IgnoreCase Or RegexOptions.Compiled)
Private ApplicationContext As HttpApplication
Private BeginRequestEventHandler As EventHandler
Private ErrorEventHandler As EventHandler
#End Region
#Region "Init and Dispose"
Public Overrides Sub Dispose() Implements System.Web.IHttpModule.Dispose
RemoveHandler ApplicationContext.BeginRequest, BeginRequestEventHandler : BeginRequestEventHandler = Nothing
RemoveHandler ApplicationContext.Error, ErrorEventHandler : ErrorEventHandler = Nothing
End Sub
Public Overridable Overloads Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
ApplicationContext = context
AddHandler ApplicationContext.BeginRequest, AddressOf OnBeginRequest
AddHandler ApplicationContext.Error, AddressOf OnError
End Sub
#End Region
Protected Sub OnBeginRequest(ByVal sender As Object, ByVal e As EventArgs)
''# Crap in here about redirecting WWW
End Sub
Protected Sub OnError(ByVal sender As Object, ByVal e As EventArgs)
''# crap in here about logging errors
End Sub
Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
''# MapRoute takes the following parameters, in order:
''# (1) Route name
''# (2) URL with parameters
''# (3) Parameter defaults
routes.MapRoute( _
"Default", _
"{controller}/{action}/{id}", _
New With { _
.controller = "Home", _
.action = "Index", _
.id = UrlParameter.Optional} _
)
End Sub
Sub Application_Start()
AreaRegistration.RegisterAllAreas()
RegisterRoutes(RouteTable.Routes)
End Sub
End Class
web.Config
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<add name="_Global" type="UrbanNow.hClassLib.MvcApplication"/>
</modules>
</system.webServer>
I have successfully created an iHttpModule to replace my Global.asax file in many Web Forms applications. But in looking at the Global.asax file in my MVC application, the methods are totally different.
I'm wondering if it is still possible to create this same thing in an MVC app. I know it's not necessary and the Global.asax works just fine. I suppose I just want to have nothing but the web.config in the root directory of my application.
Also, I am putting all of my classes in a separate class library project instead of a folder in my MVC application. Not sure if this makes a difference or not.
Here's what I have currently, but unfortunately my routes are not registering
MVCApplication.vb (Class)
Imports System.Web.Mvc
Imports System.Web.Routing
Imports System.Web
Imports System.Text.RegularExpressions
Public Class MvcApplication : Inherits System.Web.HttpApplication : Implements IHttpModule
#Region "Global Variables/Objects"
Private UrlRegex As New Regex("(http|https)://www\.", RegexOptions.IgnoreCase Or RegexOptions.Compiled)
Private ApplicationContext As HttpApplication
Private BeginRequestEventHandler As EventHandler
Private ErrorEventHandler As EventHandler
#End Region
#Region "Init and Dispose"
Public Overrides Sub Dispose() Implements System.Web.IHttpModule.Dispose
RemoveHandler ApplicationContext.BeginRequest, BeginRequestEventHandler : BeginRequestEventHandler = Nothing
RemoveHandler ApplicationContext.Error, ErrorEventHandler : ErrorEventHandler = Nothing
End Sub
Public Overridable Overloads Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
ApplicationContext = context
AddHandler ApplicationContext.BeginRequest, AddressOf OnBeginRequest
AddHandler ApplicationContext.Error, AddressOf OnError
End Sub
#End Region
Protected Sub OnBeginRequest(ByVal sender As Object, ByVal e As EventArgs)
''# Crap in here about redirecting WWW
End Sub
Protected Sub OnError(ByVal sender As Object, ByVal e As EventArgs)
''# crap in here about logging errors
End Sub
Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
''# MapRoute takes the following parameters, in order:
''# (1) Route name
''# (2) URL with parameters
''# (3) Parameter defaults
routes.MapRoute( _
"Default", _
"{controller}/{action}/{id}", _
New With { _
.controller = "Home", _
.action = "Index", _
.id = UrlParameter.Optional} _
)
End Sub
Sub Application_Start()
AreaRegistration.RegisterAllAreas()
RegisterRoutes(RouteTable.Routes)
End Sub
End Class
web.Config
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<add name="_Global" type="UrbanNow.hClassLib.MvcApplication"/>
</modules>
</system.webServer>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您希望将 MVC 的哪些方面推送到 IHttpModule 中?此场景的问题在于,每个请求都会执行 IHttpModule,而 Global.asax 方法(主要)用于执行首次运行的应用程序配置。您究竟想要实现什么目标?
您可以改为子类化 HttpApplication 类,并在代码中继承该类,因此在您的支持库中,执行如下操作:
并将 Global.asax.cs 类更改为从 MyCustomApplication 而不是 HttpApplication 继承。
What aspects of MVC do you want to push into your IHttpModule? The problem with this scenario is that an IHttpModule is executed on each request, whereas the Global.asax method is used (mostly) for performing first-run application configuration. What exactly are you trying to achieve?
You can subclass the HttpApplication class instead, and inherit from that in code, so in your supporting library, do something like this:
And change your Global.asax.cs class to inherit from MyCustomApplication instead of HttpApplication.
我刚刚遇到这个问题,寻找有关同一问题的信息。根本问题是路由模型被设计为与 HttpApplication 类一起使用,该类基本上是一个自动注册的 IHttpHandler 实例,具有某种状态巫术,而不是像我们可以在 web.config 中创建和注册的那样的适当的 IHttpModule。
在我尝试将 MVC 管道移出主 Web 项目并移入 IHttpModule 时,我遇到了多个路由注册的问题,因为据我所知,有时会执行
Init()
方法在应用程序域内多次。因此,当第二次(或第三次)调用Init()
时,RouteTable 已经准备好所有内容,并且在尝试注册重复路由期间抛出异常(在本例中为 '默认'默认)。我不确定是什么原因导致这种情况,因为我从未在正常的 ASP.NET 项目中见过它。也许这是 MVC 特有的东西。(明显的)解决方案是检查已注册的路由数量,如果不为零则停止:
这是从添加到默认 MVC 项目的 Global.asax 粘贴的股票代码,位于一个单独的 IHttpModule 实现中集会。
这有效,但我感觉不到爱。似乎只是为了摆脱 Global.asax 付出了很大的努力。我仍然需要在这里分离关注点 - 路由逻辑应该存在于一个单独的类中。但我猜我将使用某种代理模式,该模式根据某些配置设置在 Global.asax 中创建,并根据正在处理的事件根据需要进行调用。
希望这有助于有人在谷歌上搜索 mvc MapRoute IHttpModule :)
I just ran across this looking for information on the same issue. The underlying problem is that the routing model is designed to work with the HttpApplication class, which is basically an automagically registered IHttpHandler instance with some state voodoo rather than an proper IHttpModule like the ones we can create and register in web.config.
In my attempt to move the MVC plumbing out of the main web project and into an IHttpModule I ran into the problem of multiple route registration, because as far as I can see,
Init()
method is sometimes executed more than once within the app domain. So by the time the second (or third) call toInit()
came along, the RouteTable already had everything in place and an exception was thrown during the attempt to register duplicate routes (in this case the 'Default' default). I'm not sure what causes this, as I'd never seen it in normal ASP.NET projects. Perhaps it's something specific to MVC.The (apparent) solution is to check the number of routes already registered and stop if it's anything other than zero:
This is the stock code pasted from the Global.asax added to a default MVC project, in an IHttpModule implementation that lives in a separate assembly.
This works, but I'm not feeling the love. It seems like a lot of effort just to get rid of Global.asax. I still need the separation of concerns here - the route logic should live in a separate class. But I'm guessing I'm going to go with using some kind of surrogate pattern that gets created in Global.asax based on some configuration setting, and called as needed depending on the event being handled.
Hope this helps someone googling for mvc MapRoute IHttpModule :)