ASP.NET MVC — какова самая ранняя точка в цикле запроса, когда вы можете обнаружить запрос статического ресурса?

Чтобы дать этому вопросу некоторый контекст, я написал профилировщик, который вызывается для Application_BeginRequest, но он регистрирует все (например, javascripts, изображения и т. д.). Хотя в крайнем случае можно было бы добавить фильтрацию к клиенту профилировщика, я бы предпочел активировать профилировщик только тогда, когда можно определить, что запрос требует маршрутизации. В идеале это было бы в Application_BeginRequest, но я не думаю, что это было бы возможно без избыточной обработки входящего запроса на маршрутизацию...

Короче говоря, когда наступает самая ранняя точка жизненного цикла запроса, когда я могу определить, относится ли запрос к статическому ресурсу или нет, и как бы вы это сделали?

Возможно ли получить или подключиться к System.Web.Routing.RouteTable и оттуда вызвать мой код профилировщика?


person nathanchere    schedule 26.07.2011    source источник


Ответы (3)


Существуют различные варианты. Сначала — определить статический файл с помощью Request.PhysicalPath — проверить: Check для статического файла во время Application_BeginRequest?

Одной из альтернатив может быть использование этого в качестве обработчика и использование пути для указания типов файлов, которые необходимо включить (*.aspx), например, в ваш файл web.config. Затем вы можете получить доступ к событиям довольно рано (см. Конвейер asp.net)

Или просто используйте httpmodule - проверьте все и профилируйте только нефизические элементы, как вы упомянули.

Или - используйте свой текущий метод с первой ссылкой, чтобы просто проверить Request.PhysicalPath и надеяться, что это сработает для вас :)

person Adam Tuliper - MSFT    schedule 26.07.2011
comment
Проблема с подходом Request.PhysicalPath заключается в том, что он предполагает, что запрос является статическим, если запрос может напрямую отображаться в имя файла, и не является статическим запросом, если нет. Я не хочу, например, чтобы ссылка с неправильным названием или ссылка на удаленный файл изображения интерпретировались как нестатическая ссылка только потому, что файл не существует на диске. - person nathanchere; 28.07.2011
comment
Затем ваш код может захотеть проверить код ответа, чтобы определить этот случай (хотя то же самое может применяться к отсутствующему динамическому файлу), потому что по определению выше физический файл является статическим, и вы ищете статический тип файла. Чтобы действительно обнаружить это, вам нужно либо сделать предположения о типе файла, либо запросить iis или конфигурацию приложений для всех его сопоставлений. Технически я могу сделать .js динамическим файлом, просто сопоставив его с aspnet_isapi или другим httphandler, так где вы хотите провести линию? - person Adam Tuliper - MSFT; 29.07.2011

Я бы предпочел использовать фильтры MVC для профилирования, поскольку фильтры MVC позволяют добавлять поведение до и после обработки, а параметр filterContext должен предоставить вам достаточно информации.

Например, я бы создал ProfilerAttribute для профилирования

public class ProfilerAttribute : FilterAttribute, IActionFilter, IResultFilter, IExceptionFilter {
    public void OnActionExecuting(ActionExecutingContext filterContext) {
        Debug.WriteLine("Before Action is executing");
    }

    public void OnActionExecuted(ActionExecutedContext filterContext) {
        Debug.WriteLine("After Action is executed");
    }

    public void OnResultExecuted(ResultExecutedContext filterContext) {
        Debug.WriteLine("After Action Result is executed");            
    }

    public void OnResultExecuting(ResultExecutingContext filterContext) {
        Debug.WriteLine("Before Action Result is executing");
    }

    public void OnException(ExceptionContext filterContext) {
        Debug.WriteLine("oops! exception");
    }
}

и зарегистрируйтесь как GlobalFilter в Global.ascx....

public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
    filters.Add(new HandleErrorAttribute());
    filters.Add(new ProfilerAttribute());
}

Надеюсь, это поможет. Спасибо.

обновление: забыл упомянуть, что фильтр MVC выполняется только после сопоставления маршрутизации. Таким образом, вам не нужно отфильтровывать статические ресурсы, поскольку это уже было сделано MVC.

person Soe Moe    schedule 26.07.2011
comment
Первоначально я использовал вызовы ActionExecuting и actionExecuted производного класса контроллера, но проблема в том, что он пропускает такие вещи, как рендеринг View, маршрутизация и т. д., которые я хочу иметь возможность профилировать. - person nathanchere; 27.07.2011
comment
Реализуя IResultFilter, вы можете профилировать, например, визуализацию View, если результатом вашего действия является ViewResult. Таким образом, вы будете знать, является ли действие контроллера медленным или результат выполнения медленным. Поскольку маршрутизация является частью Asp.net, вы мало что можете сделать для повышения производительности. Для профилирования среды выполнения ASP.NET можно использовать счетчики производительности для ASP.NET. goo.gl/uRB8f :) - person Soe Moe; 27.07.2011
comment
Эта статья журнала MSDN также может быть вам полезна. -us/magazine/hh288078.aspx - person Soe Moe; 27.07.2011

Я пробовал подходить к этому с другой стороны, и я намного более доволен результатом. По сути, зачем обнаруживать статические запросы ресурсов, если вы можете вообще не «маршрутизировать» их? В global.asax:

private readonly string[] STATIC_CONTENT_PATHS = new string[] { "css", "js", "img" }; 

public static void RegisterRoutes(RouteCollection routes)
{    
    foreach (string path in STATIC_CONTENT_PATHS) { routes.IgnoreRoute(path + @"/{*foo}"); }

    // other MapRoute calls here
}

Теперь мне больше не нужно проверять статические запросы, хотя, если я по какой-то причине захочу, я все еще могу сделать следующее:

protected void Application_BeginRequest()
{            
    if (IsStaticRequest())
    {
         // do something here
    }
}

private bool IsStaticRequest()
{
   var result = Request.Url.AbsolutePath.Split('/');
   if (result.Length < 2) return false;
   return STATIC_CONTENT_PATHS.Contains(result[1]);
}

Поскольку я абсолютно точно знаю, какие единственные пути, по которым я буду обслуживать статический контент, это кажется довольно надежным решением. Я все еще открыт для других идей, но я думаю, что это соответствует моим потребностям.

person nathanchere    schedule 26.07.2011