MVC Controller Action that doesn't modify existing response

时间:2015-07-08 16:01:42

标签: c# asp.net-mvc asp.net-mvc-4 web-config

In short, I've written an error handler controller that has a "HandleError" action that handles all http errors that I care to handle.

For a few reasons (outlined in this answer), I'm catching http errors in two places. One is a global Application_EndRequest method (managed pipeline) and the other is via the <httpErrors> section in the web config (native custom errors module).

If you're wondering why I need the <httpErrors> section, it's because certain responses aren't always caught by the managed pipeline, for example the StaticFile handler catches all urls like ".html,.txt" and will not trigger MVC code.

My controller action looks close to this

public ActionResult HandleError(int statusCode = 0, Exception exception = null)
    {
      string responseProcessed = Request.Headers.Get("__p__");

      if (responseProcessed == null)
      {
        Request.Headers.Add("__p__", "1");

        switch (statusCode)
        {
          case 401:
            return Unauthorized();
          case 403:
            return Forbidden();
          case 404:
            return NotFound();
          case 500:
            return InternalError(exception);
          default:
            return UnhandledError(exception, statusCode);
        }
      }
      else
      {
        return null;
      }
    }

My web.config httpErrors section is currently

<httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404"/>
      <error statusCode="404" path="/Errors/HandleError?statusCode=404" responseMode="ExecuteURL"/>
</httpErrors>

Problem

The problem is, the HandleError method is called twice per 404 response because it first hits the custom errors module (specified via the web.config) and then my Application_EndRequest hook catches the 404 which also triggers my action.

Question

The question is, how can I make my HandleError action do nothing to the response instead of replacing it with a blank response (which is what happens when you return null in an action).

Note

Please note that I am aware that I can make my custom 404 error (in web.config) point to my NotFound action explicitly and just return the view each time even though it gets called twice. There is logic (logging, etc) that still needs to only run once and I think it's better design to have it all point to the HandleError method instead to keep repetitive checking logic down and to only runs the action once.

2 个答案:

答案 0 :(得分:0)

简单的答案是......你不能。无论如何,所有操作方法都返回一种ActionResult。如果您不需要actionresult(或返回null时发送的默认EmptyResult),则不要使用action方法,而是考虑使用私有方法。

如果这样做,您可以按照自己的建议使用自定义404,然后根据需要从控制器中调用此私有HandleError方法。

如果每个请求都需要运行此逻辑,那么请考虑将其放在动作过滤器中。

答案 1 :(得分:0)

我认为你可以,但你可能会让事情变得复杂。让我们先看看:)这是否解决了静态文件的错误处理问题?

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

您可以在此处详细了解:http://www.hanselman.com/blog/BackToBasicsDynamicImageGenerationASPNETControllersRoutingIHttpHandlersAndRunAllManagedModulesForAllRequests.aspx