Переместите Global.asax в iHttpModule при использовании ASP.NET MVC - PullRequest
2 голосов
/ 06 июня 2010

Я успешно создал iHttpModule для замены моего файла Global.asax во многих приложениях Web Forms.Но, глядя на файл Global.asax в моем приложении MVC, методы совершенно разные.

Мне интересно, возможно ли все еще создать эту же вещь в приложении 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>

Ответы [ 2 ]

4 голосов
/ 07 июня 2010

Какие аспекты MVC вы хотите добавить в свой IHttpModule? Проблема этого сценария заключается в том, что IHttpModule выполняется для каждого запроса, тогда как метод Global.asax используется (в основном) для выполнения настройки приложения при первом запуске. Что именно вы пытаетесь достичь?

Вместо этого вы можете создать подкласс класса HttpApplication и наследовать от него в коде, поэтому в вашей вспомогательной библиотеке сделайте что-то подобное:

public class MyCustomApplication : HttpApplication
{
    public void Application_Start() {

    }
}

И измените свой класс Global.asax.cs на наследование от MyCustomApplication вместо HttpApplication.

0 голосов
/ 11 октября 2010

Я только что наткнулся на это в поисках информации по той же проблеме. Основная проблема заключается в том, что модель маршрутизации предназначена для работы с классом HttpApplication, который в основном представляет собой автоматически зарегистрированный экземпляр IHttpHandler с некоторым состоянием voodoo, а не с собственным IHttpModule, подобным тем, которые мы можем создать и зарегистрировать в web.config.

В моей попытке переместить трубопровод MVC из основного веб-проекта в IHttpModule я столкнулся с проблемой регистрации нескольких маршрутов, потому что, насколько я вижу, метод Init() иногда выполняется более одного раза внутри домен приложения. Таким образом, к тому времени, когда пришел второй (или третий) вызов Init(), в RouteTable уже было все на месте, и при попытке зарегистрировать дублирующиеся маршруты было сгенерировано исключение (в данном случае значение по умолчанию «Default»). Я не уверен, что вызывает это, поскольку я никогда не видел это в обычных проектах ASP.NET. Возможно, это что-то особенное для MVC.

(Очевидное) решение состоит в том, чтобы проверить количество уже зарегистрированных маршрутов и остановить его, если оно равно нулю:

public void Init(HttpApplication context) {
    if (RouteTable.Routes.Count == 0) {

        RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        RouteTable.Routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
        );
    }
}

Это стандартный код, вставленный из Global.asax, добавленного в проект MVC по умолчанию, в реализации IHttpModule, которая находится в отдельной сборке.

Это работает, но я не чувствую любви. Кажется, что нужно приложить немало усилий, чтобы избавиться от Global.asax. Мне все еще нужно разделение проблем здесь - логика маршрута должна жить в отдельном классе. Но я предполагаю, что собираюсь использовать какой-то суррогатный шаблон, который создается в Global.asax на основе некоторого параметра конфигурации и вызывается по мере необходимости в зависимости от обрабатываемого события.

Надеюсь, это поможет кому-то поискать по телефону mvc MapRoute IHttpModule :)

...