如何在 WebAPI 中返回 404 和 403 的 json
本文关键字:json 返回 WebAPI | 更新日期: 2023-09-27 18:35:20
我有一个相当简单的Web API应用程序,目前有一个路由设置。 如果用户尝试访问任何其他路由,他们会得到 404,但 404 的正文是 HTML 而不是 JSON(这是他们的接受标头所要求的)。 让 IIS 使用 JSON 错误响应而不是网页来响应不存在的路由请求的最简单方法(添加到我的项目中的代码/配置最少)是什么?
同样的问题也适用于403。 如果我尝试导航到应用程序的根目录,我会再次返回 403 作为网页。 我希望这是 404,但更大的问题是我如何使来自应用程序的所有响应都是 JSON,而不仅仅是有效路由上的响应? 我之所以提到 403,是因为我正在寻找一种更广泛的解决方案,而不仅仅是设置一条包罗万象的路由,因为我认为这对我处理 403 或控制器操作之外发生的任何其他随机异常都没有帮助。
最好是,我希望我的应用程序尊重请求上的接受标头。 但是,由于我的 API 现在只支持 JSON,我愿意(暂时)接受它总是使用 JSON 响应。
我正在使用WebAPI 2.2和.NET 4.5.2。
编辑
这不是格式化程序问题。 格式化程序正确应用于成功的消息,遵循请求中的接受标头。 这特别是未处理的路由和 Web 服务器错误(例如尝试访问 Web 根目录时禁止)的问题。
编辑 2
重现步骤:
- 打开 Visual Studio 2013 Update 4
- 新项目
- 选择 .NET Framework 4.5.2
- 选择> Visual C#> Web> ASP.NET Web 应用程序的模板
- 选择"空",取消选中所有文件夹和核心引用。
- 右键单击项目>将>新的基架项添加到 Web API 2 控制器> - 空
- 修改默认控制器,如下所示。
- 修改 WebApiConfig.cs如下所示。
- 运行/调试
我期望的是,当我导航到http://localhost:<port>/api/do_stuff
时,我会看到 XML 或 JSON 中的Success!
,具体取决于接受标头(我这样做),当我导航到任何其他页面时,我应该看到Failure!
(我没有)。 相反,当我导航到任何其他页面时,我看到 IIS 的 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
在上面的例子中,当我尝试导航到无效路由或导航到站点根目录时,两者都没有调用。
若要将 IIS 配置为对不存在的路由和其他服务器错误使用 JSON 错误响应进行响应,可以使用 web.config 文件中的自定义错误功能。以下是您可以执行的操作:
在 Visual Studio 中打开您的项目。在项目的根目录中找到 web.config 文件。添加或修改
<system.web>
<customErrors mode="On" defaultRedirect="~/error" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="~/error/notfound" />
<error statusCode="403" redirect="~/error/forbidden" />
</customErrors>
</system.web>
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="403" subStatusCode="-1" />
<error statusCode="404" path="~/error/notfound" responseMode="ExecuteURL"/>
<error statusCode="403" path="~/error/forbidden" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
在项目的根目录中创建一个名为"错误"的新文件夹。在"错误"文件夹中,创建两个新文件:"NotFound.cshtml"和"Forbidden.cshtml"(如果您使用的是 Razor 页面.cs则为 .cshtml),其中包含以下内容:NotFound.cshtml:
@{
Response.StatusCode = 404;
Layout = null;
}
{"error": "Not found"}
Forbidden.cshtml:
@{
Response.StatusCode = 403;
Layout = null;
}
{"error": "Forbidden"}
这些文件将返回具有相应状态代码的 JSON 错误响应。
现在,当用户尝试访问不存在的路由时,他们将收到 JSON 错误响应,而不是默认的 404 HTML 页面。同样,在访问应用程序的根目录时,403 响应将以 JSON 形式返回。
确保根据需要调整错误消息和格式。
从计划的 catch-all-route 调用下面的函数以返回如下所示的 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);
调用 httpget 以获取响应 404 未找到 使用这个
public JsonResult DoSomething() {
try
{
var result = getData();
return Json(result, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(HttpNotFound());
}
}