1

To give the question some context, I've written a profiler which is called on Application_BeginRequest but it's logging everything (ie javascripts, images etc). While it would be possible as a last resort to add filtering to the profiler client, I'd much rather only activate the profiler when it can be determined that the request requires routing. Ideally it would be in Application_BeginRequest but I don't think it would be possible without redundant processing of the incoming request for routing...

So in short, when is the earliest point in the request life cycle that I can determine if a request is for a static resource or not, and how would you go about it?

Is it perhaps possible to derive from or hook into System.Web.Routing.RouteTable and call my profiler code from there?

nathanchere
  • 8,008
  • 15
  • 65
  • 86

3 Answers3

2

There are various options. First - to determine the static file using Request.PhysicalPath - check out: Check for a static file during Application_BeginRequest?

One alternative would be to have this as a handler and use the path to note the file types to include (*.aspx) for example in your web.config. Then you can have access to events pretty early on (see asp.net pipeline)

Or just use an httpmodule - check everything and only profile the non-physical items as you mention.

Or - use your current method with the first link to simply check Request.PhysicalPath and hope that works for you : )

Community
  • 1
  • 1
Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • The problem with the Request.PhysicalPath approach is it assumes that a request is static if the request can map directly to a file name, and is not a static request if not. I don't want, for example, a mis-named link or a reference to a deleted image file to be interpreted as a non-static link just because the file doesnt' exist on the disk. – nathanchere Jul 27 '11 at 23:44
  • Then your code may want to check the response code to determine this case (although the same could apply for a missing dynamic file) because by definition the above is a physical file is static and you are looking for a static file type. To truly detect that you either need to make file type assumptions or query iis or the apps config for all it's mappings. Technically I can have .js be a dynamic file simply by mapping it to aspnet_isapi or another httphandler so where do you want to draw the line at? – Adam Tuliper Jul 29 '11 at 06:05
2

I would rather use MVC Filters for profiling since MVC Filters allow to add pre- and post-processing behaviours and filterContext parameter should give you enough information.

For example, I would create ProfilerAttribute for profiling

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");
    }
}

and register as GlobalFilter in Global.ascx....

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

Hope it can help. Thanks.

update: Forgot to mention that the MVC Filter only executed after the routing is matched. So, you don't need to filter out for static resources since it was already done by MVC.

Soe Moe
  • 3,428
  • 1
  • 23
  • 32
  • I was originally using calls on ActionExecuting and actionExecuted of a derived controller class but the problem is it misses things like View rendering, routing etc which are things I want to be able to profile. – nathanchere Jul 27 '11 at 02:13
  • 1
    By implementing IResultFilter, you can profile like View rendering if your action result is ViewResult. So, you will know whether controller action is slow or executing result is slow. Since routing is part of Asp.net, you can't do much about it for performance. For profiling ASP.NET runtime, you can use Performance Counters for ASP.NET. http://goo.gl/uRB8f :) – Soe Moe Jul 27 '11 at 13:12
  • This MSDN Magazine article might useful for you too.. http://msdn.microsoft.com/en-us/magazine/hh288078.aspx – Soe Moe Jul 27 '11 at 13:16
1

I've tried approaching it from a different angle and am much happier with the result. Basically - why detect static resource requests when you can just not 'route' them at all? In 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
}

Now I no longer need to check for static requests, although if I do want to for whatever reason I can still do the following:

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]);
}

Since I know with absolute certainly what the only paths I'll be serving static content from are, this seems like a fairly robust solution. I'm still open to other ideas but I think this suits my needs well.

nathanchere
  • 8,008
  • 15
  • 65
  • 86