[英]Mixing MVC and Web API Error Handling
We have an MVC 4
web application where we use the web.config
file to handle custom errors. 我们有一个MVC 4
Web应用程序,我们在其中使用web.config
文件来处理自定义错误。
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/AccessDenied" />
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
<remove statusCode="500" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error/ApplicationError" />
</httpErrors>
</system.webServer>
All ,of which works as expected. 所有这些都按预期工作。
We are now beginning to implement some new features in this project using AngularJS
and Web API
. 现在,我们开始使用AngularJS
和Web API
在此项目中实现一些新功能。 In our Web API
controller actions, we are consistently returning a HttpResponseMessage to indicate success/failure of the call. 在我们的Web API
控制器操作中,我们将始终返回HttpResponseMessage来指示调用成功/失败。 For example: 例如:
return Request.CreateResponse(HttpStatusCode.BadRequest, result);
The problem (I think!) we are having is that originally MVC
error handling is intercepting the BadRequest
result (as is reasonable) so that the HttpResponseMessage
result data never gets returned to the calling AngularJS
method. 我们遇到的问题(我认为!)是,最初的MVC
错误处理正在拦截BadRequest
结果(合理),因此HttpResponseMessage
结果数据永远不会返回到调用的AngularJS
方法。
What is the best way to handle errors in this mixed ( MVC/Web API
) environment so that the Web API
HttpResponseMessages
are not lost? 在这种混合( MVC/Web API
)环境中处理错误的最佳方法是什么,以使Web API
HttpResponseMessages
不丢失?
Thanks. 谢谢。
I am not sure I have found the best solution, but in the end I removed the httpErrors section from the Web.config and built my own error handler in the Global.asax assisted by the following posts: 我不确定是否找到了最佳的解决方案,但是最后我从Web.config中删除了httpErrors部分,并在以下帖子的帮助下在Global.asax中构建了自己的错误处理程序:
Global.asax Global.asax
public void Application_Error(Object sender, EventArgs e)
{
var httpContext = ((MvcApplication) sender).Context;
var currentController = "";
var currentAction = "";
var currentRouteData =
RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData != null)
{
if (
!String.IsNullOrEmpty(
currentRouteData.Values["controller"]?.ToString()))
{
currentController = currentRouteData.Values["controller"].ToString();
}
if (!String.IsNullOrEmpty(currentRouteData.Values["action"]?.ToString()))
{
currentAction = currentRouteData.Values["action"].ToString();
}
}
var ex = Server.GetLastError();
var httpEx = ex as HttpException;
var controller = new ErrorController();
var routeData = new RouteData();
var statusCode = httpEx?.GetHttpCode() ?? 500;
string action;
switch (statusCode)
{
case 400:
action = "BadRequest";
break;
case 403:
action = "AccessDenied";
break;
case 404:
action = "NotFound";
break;
default:
action = "Index";
break;
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = statusCode;
httpContext.Response.TrySkipIisCustomErrors = true;
if (statusCode >= 500)
{
Server.Transfer("/Error/ServerError.html");
return;
}
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
routeData.Values["statusCode"] = statusCode;
controller.ViewData.Model = new HandleErrorInfo(ex, currentController,
currentAction);
((IController) controller).Execute(
new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
My error controller then looked like this: 然后,我的错误控制器如下所示:
[AllowAnonymous]
public sealed class ErrorController
: AblController
{
public ActionResult Index(int statusCode)
{
ViewBag.StatusCode = statusCode;
return View("Error");
}
// HTTP 400 - Bad Request
public ActionResult BadRequest()
{
// Now handled by Global.asax - Application_Error
// Response.StatusCode = (int) HttpStatusCode.BadRequest;
// Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
return Json(
new
{
error = new ErrorSummary("Bad Request")
});
}
return View();
}
// HTTP 403 - Access Denied
public ActionResult AccessDenied()
{
// Now handled by Global.asax - Application_Error
// Response.StatusCode = (int) HttpStatusCode.Forbidden;
// Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
return Json(
new
{
error = new ErrorSummary("Access Denied")
});
}
return View();
}
// HTTP 404 - Not Found
public ActionResult NotFound()
{
// Now handled by Global.asax - Application_Error
// Response.StatusCode = (int) HttpStatusCode.NotFound;
// Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
return Json(
new
{
error = new ErrorSummary("Not Found")
});
}
return View();
}
}
} }
I also turned the custom error mode off in the Web.config 我还关闭了Web.config中的自定义错误模式
<customErrors mode="Off" />
This solution needs more testing , but so far it seems to be performing as expected/as required. 该解决方案需要更多的测试 ,但到目前为止,它似乎正在按预期/要求执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.