ASP.NET MVC 4 перехоплює всі вхідні запити


78

Чи є у мене спосіб перехопити всі вхідні запити до мого додатка ASP.NET MVC 4 і запустити деякий код, перш ніж продовжувати запит до вказаного контролера / дії?

Мені потрібно запустити певний власний код автентифікації з існуючими службами, і, щоб зробити це належним чином, мені потрібно мати можливість перехоплювати всі вхідні запити від усіх клієнтів, щоб перепровірити деякі речі з іншою службою.


7
Див. Мою статтю про фільтрацію msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx
RickAndMSFT

Відповіді:


80

Найбільш правильним способом було б створити клас, який успадковує ActionFilterAttribute і OnActionExecutingметод override . Потім це можна зареєструвати GlobalFiltersвGlobal.asax.cs

Звичайно, це буде перехоплювати лише запити, які насправді мають маршрут.


10
Єдиним (негарним) іншим є protected void Application_BeginRequest(object sender, EventArgs e).
Ерік Філіпс,

1
Ну, я думаю, ви також можете створити HttpHandler і зареєструвати його, щоб ловити все в web.config, але це справді брудно :)
Yngve B-Nilsen

1
Чи є спосіб примусити перенаправлення зсередини OnActionExecutingзаміни?
Джессі

2
Так, ви можете встановити filterContext.Result на RedirectResult
Yngve B-Nilsen

1
Ви можете змінити результат на будь-який тип ActionResult, який вважаєте за потрібне
Yngve B-Nilsen

38

Для цього ви можете використовувати 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>

3
Якщо метою є захоплення запитів додатків MVC до того, як вони переходять до контролера, фільтрація є набагато кращим підходом. Дивіться мою статтю msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx - мій зразок має приємний фільтр синхронізації
RickAndMSFT

1
Я б рекомендував не використовувати цей підхід, оскільки він використовує, runAllManagedModulesForAllRequestsщо є затримкою продуктивності. Application_BeginRequestздається набагато простішим способом досягнення результату
Кванго

25

Я думаю, що ви шукаєте ось що:

Application_BeginRequest()

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

Ви вкладаєте його Global.asax.cs.

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

Я використовую це для налагодження, але я не впевнений, наскільки це вдале рішення для вашого випадку.


2

Я не впевнений у MVC4, але я думаю, що він досить схожий на MVC5. Якщо ви створили новий веб-проект -> загляньте, Global.asaxі ви побачите наступний рядок FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);у методі Application_Start().

RegisterGlobalFilters- це метод у файлі, який FilterConfig.csзнаходиться в папці App_Start.

Як сказав @ 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()); .

Тепер ви можете ловити всі вхідні запити та змінювати їх.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.