我有一个相当简单的web api应用程序,目前只有一个路由设置。如果用户试图访问任何其他路由,他们会返回404,但404的主体是html,而不是json(这是他们的accept头所要求的)。什么是最简单(最少的代码/配置添加到我的项目)的方式,使IIS响应非存在的路线的请求与JSON错误响应,而不是网页?
同样的问题也适用于403。如果我试图导航到我的应用程序的根,我会得到一个403,再次作为网页。我希望这是404,但更大的问题是,如何使应用程序中的所有响应都是json,而不仅仅是有效路由上的响应?我提到403是因为我正在寻找一个更广泛的解决方案,而不仅仅是设置一个全部捕获的路由,因为我不相信这会帮助我处理403或发生在控制器操作之外的任何其他随机异常。
更愿意的是,我希望我的申请能够尊重请求的accept头。但是,由于我的api现在只支持json,所以我愿意(暂时)使用它总是用json响应。
我正在使用webapi 2.2和.net 4.5.2。
编辑
这不是格式化程序的问题。格式化程序正确地应用于成功的消息,与请求中的accept头相关。这特别是与未处理的路由和Web服务器错误有关的问题(例如,尝试访问Web根目录时禁止)。
编辑2
复制步骤:
打开Visual Studio 2013更新4
新建项目
选择.NET Framework 4.5.2
选择模板>Visual C>Web>ASP.NET Web应用程序
选择“空”,不选中所有文件夹和核心引用。
右键单击项目>添加>新建scaffold项>web api 2控制器-空
修改defaultcontroller,如下所示。
修改webapiconfig.cs,如下所示。
运行/调试
我所期望的是,当我导航到http://localhost:<port>/api/do_stuff
时,根据accept headers(我这样做)可以在xml或json中看到Success!
,当我导航到任何其他页面时,我应该看到Failure!
(我不这样做)。相反,当我导航到任何其他页面时,我会看到i i s的404响应。
默认控制器.cs:
[RoutePrefix("api")]
public class DefaultController : ApiController
{
[HttpGet]
[Route("do_stuff")]
public String DoStuff()
{
return "Success!";
}
}
webapiconfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Filters.Add(new CustomExceptionFilter());
}
private class CustomExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
actionExecutedContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.NotFound)
{
Content = new StringContent(@"""Failure!"""),
};
}
}
}
}
编辑3
我还尝试添加全局异常处理程序和异常记录器,如下所示:
http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling
在上面的示例中,当我尝试导航到无效路由或导航到站点根目录时,两者都不会被调用。
最佳答案
从计划的catch all路由调用下面的函数以返回如下jsonresult操作
public JsonResult Handle404()
{
return Json(new { error404 = "NOT FOUND", Message = "Additional Message" });
}
会产生
var result =
{
"error404": "NOT FOUND",
"Message": "Additional Message"
};
alert(result.error404);
allert(result.Message);