【问题标题】:ASP.NET MVC 4 intercept all incoming requestsASP.NET MVC 4 拦截所有传入请求
【发布时间】:2012-07-28 10:28:53
【问题描述】:

有没有办法让我捕获 所有 对我的 ASP.NET MVC 4 应用程序的传入请求并运行一些代码,然后再继续将请求转发到指定的控制器/操作?

我需要使用现有服务运行一些自定义身份验证代码,并且要正确执行此操作,我需要能够拦截来自所有客户端的所有传入请求,以仔细检查其他服务的某些内容。

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-4


【解决方案1】:

我不确定 MVC4,但我认为它与 MVC5 非常相似。如果您创建了一个新的 Web 项目 -> 查看 Global.asax,您应该会在方法 Application_Start() 中看到以下行 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

RegisterGlobalFilters 是位于文件夹App_Start 中的文件FilterConfig.cs 中的一个方法。

正如@YngveB-Nilsen 所说,ActionFilterAttribute 在我看来是要走的路。添加一个派生自System.Web.Mvc.ActionFilterAttribute 的新类。这很重要,因为System.Web.Http.Filters.ActionFilterAttribute 将失败,例如以下异常。

给定的过滤器实例必须实现以下一项或多项 过滤器接口:System.Web.Mvc.IAuthorizationFilter, System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter, System.Web.Mvc.IExceptionFilter, System.Web.Mvc.Filters.IAuthenticationFilter.

将请求写入调试窗口的示例:

public class DebugActionFilter : System.Web.Mvc.ActionFilterAttribute
{
  public override void OnActionExecuting(ActionExecutingContext actionContext)
  {
    Debug.WriteLine(actionContext.RequestContext.HttpContext.Request);
  }
}

FilterConfig -> RegisterGlobalFilters -> 添加以下行:filters.Add(new DebugActionFilter());

您现在可以捕获所有传入的请求并修改它们。

【讨论】:

    【解决方案2】:

    我认为你搜索的是这样的:

    Application_BeginRequest()
    

    http://www.dotnetcurry.com/showarticle.aspx?ID=126

    你把它放在Global.asax.cs

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Request.....;
        }
    

    我将它用于调试目的,但我不确定它对您的情况有多好。

    【讨论】:

      【解决方案3】:

      您可以使用 HttpModule 来完成此操作。这是我用来计算所有请求的处理时间的示例:

      using System;
      using System.Diagnostics;
      using System.Web;
      
      namespace Sample.HttpModules
      {
          public class PerformanceMonitorModule : IHttpModule
          {
      
              public void Init(HttpApplication httpApp)
              {
                  httpApp.BeginRequest += OnBeginRequest;
                  httpApp.EndRequest += OnEndRequest;
                  httpApp.PreSendRequestHeaders += OnHeaderSent;
              }
      
              public void OnHeaderSent(object sender, EventArgs e)
              {
                  var httpApp = (HttpApplication)sender;
                  httpApp.Context.Items["HeadersSent"] = true;
              }
      
              // Record the time of the begin request event.
              public void OnBeginRequest(Object sender, EventArgs e)
              {
                  var httpApp = (HttpApplication)sender;
                  if (httpApp.Request.Path.StartsWith("/media/")) return;
                  var timer = new Stopwatch();
                  httpApp.Context.Items["Timer"] = timer;
                  httpApp.Context.Items["HeadersSent"] = false;
                  timer.Start();
              }
      
              public void OnEndRequest(Object sender, EventArgs e)
              {
                  var httpApp = (HttpApplication)sender;
                  if (httpApp.Request.Path.StartsWith("/media/")) return;
                  var timer = (Stopwatch)httpApp.Context.Items["Timer"];
      
                  if (timer != null)
                  {
                      timer.Stop();
                      if (!(bool)httpApp.Context.Items["HeadersSent"])
                      {
                          httpApp.Context.Response.AppendHeader("ProcessTime",
                                                                ((double)timer.ElapsedTicks / Stopwatch.Frequency) * 1000 +
                                                                " ms.");
                      }
                  }
      
                  httpApp.Context.Items.Remove("Timer");
                  httpApp.Context.Items.Remove("HeadersSent");
      
              }
      
              public void Dispose() { /* Not needed */ }
          }
      
      }
      

      这就是您在 Web.Config 中注册模块的方式:

      <system.webServer>
          <modules runAllManagedModulesForAllRequests="true">
              <add name="PerformanceMonitorModule" type="Sample.HttpModules.PerformanceMonitorModule" />
          </modules>
      <//system.webServer>
      

      【讨论】:

      • 如果目标是在 MVC 应用程序请求到达控制器之前捕获它们,那么过滤是一种更好的方法。请参阅我的文章 msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx - 我的示例有一个不错的定时过滤器
      • 我建议不要使用这种方法,因为它使用runAllManagedModulesForAllRequests,这是一种性能拖累。 Application_BeginRequest 似乎是实现结果的一种更简单的方法
      【解决方案4】:

      最正确的方法是创建一个继承ActionFilterAttribute 的类并覆盖OnActionExecuting 方法。然后可以在GlobalFilters中注册Global.asax.cs

      当然,这只会拦截实际有路由的请求。

      【讨论】:

      • 唯一(丑陋的)其他方式是protected void Application_BeginRequest(object sender, EventArgs e)
      • 好吧,我想你也可以创建一个 HttpHandler 并注册它以在 web.config 中捕获所有内容,但这真的很脏:)
      • 有没有办法从 OnActionExecuting 覆盖中强制重定向?
      • 是的,您可以将 filterContext.Result 设置为 RedirectResult
      • 您可以将结果更改为您认为合适的任何类型的 ActionResult
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 2017-02-09
      相关资源
      最近更新 更多