Asp.net web api MVC6WebAPI返回html错误页,而不是异常对象的json版本
我正在调用MVC 6 WebAPI中的api端点:Asp.net web api MVC6WebAPI返回html错误页,而不是异常对象的json版本,asp.net-web-api,asp.net-core-mvc,Asp.net Web Api,Asp.net Core Mvc,我正在调用MVC 6 WebAPI中的api端点: POST http://localhost:57287/mytestapi/testentity/ HTTP/1.1 Accept: application/json X-APIKey: 00000000-0000-0000-0000-000000000000 Content-Type: application/json; charset=utf-8 Host: localhost:57287 Content-Length: 1837 Expe
POST http://localhost:57287/mytestapi/testentity/ HTTP/1.1
Accept: application/json
X-APIKey: 00000000-0000-0000-0000-000000000000
Content-Type: application/json; charset=utf-8
Host: localhost:57287
Content-Length: 1837
Expect: 100-continue
Connection: Keep-Alive
在正文中,我有json序列化的测试实体
我的实体控制器代码中有一个bug,api返回500响应“服务器错误”,我知道这个bug是什么,但我需要一些帮助的问题是,api返回的是HTML而不是json序列化的异常对象-json是我所期望的:旧webapi将返回json。我已经移植了一个旧的测试项目的代码,我知道它是有效的
那么为什么MVC6WebAPI返回html而不是json呢?我需要进行一些配置吗
编辑:
我按照@danludwig的建议在标题中添加了Accept:application/json,但是这并没有解决问题,我仍然返回了一个html错误页面
我查看了StartUp.cs,发现:
if (env.IsDevelopment())
{
//app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
在ConfigureApp方法中。我使用app.usedeveloperceptionpage()进行了测试;评论说。这阻止了返回api响应正文中的html错误页,但是我仍然没有得到json序列化异常对象。使用时配置的不包括对json的任何支持。它只会返回错误html页面。使用时也可以这样说
据我所知,您需要添加一些代码来处理错误并返回json
- 一个选项是使用异常过滤器,并将其全局添加或添加到选定的控制器上,尽管此方法仅涵盖来自控制器操作方法的异常。例如,只有当请求接受为application/json时,以下过滤器才会返回一个json对象(否则它会让异常通过,例如可以由全局错误页面处理):
- 另一个选项是使用
重载添加您自己的异常处理程序中间件,该重载允许您指定将处理异常的替代管道的行为。我使用内联中间件快速编写了一个类似的示例,该中间件仅在请求accept为application/json时才会返回json对象:app.UseExceptionHandler
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseExceptionHandler(appBuilder => { appBuilder.Use(async (context, next) => { var excHandler = context.Features.Get<IExceptionHandlerFeature>(); if (context.Request.GetTypedHeaders().Accept.Any(header => header.MediaType == "application/json")) { var jsonString = string.Format("{{\"error\":\"{0}\"}}", excHandler.Error.Message); context.Response.ContentType = new MediaTypeHeaderValue("application/json").ToString(); await context.Response.WriteAsync(jsonString, Encoding.UTF8); } else { //I haven't figured out a better way of signally ExceptionHandlerMiddleware that we can't handle the exception //But this will do the trick of letting the other error handlers to intervene //as the ExceptionHandlerMiddleware class will swallow this exception and rethrow the original one throw excHandler.Error; } }); });
if(env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } 其他的 { app.UseExceptionHandler(“/Home/Error”); } app.UseExceptionHandler(appBuilder=> { 使用(异步(上下文,下一步)=> { var exchHandler=context.Features.Get(); if(context.Request.GetTypedHeaders().Accept.Any(header=>header.MediaType==“application/json”)) { var jsonString=string.Format(“{{\”error\”:\“{0}\”}>,excHandler.error.Message); context.Response.ContentType=新的MediaTypeHeaderValue(“应用程序/json”).ToString(); wait context.Response.WriteAsync(jsonString,Encoding.UTF8); } 其他的 { //我还没有找到一种更好的方法来处理我们无法处理的异常 //但这样做可以让其他错误处理程序介入 //因为ExceptionHandlerMiddleware类将吞并此异常并重新调用原始异常 抛出exchHandler.Error; } }); });
如果使用第二种方法,您很可能希望将该逻辑放入自己的中间件类中,并使用不同的方法生成json响应。在这种情况下,请看一下什么是我发现了一种廉价的方法,通过将此添加到Startup Configure方法来获得我想要的:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Simple error page to avoid a repo dependency.
app.Use(async (context, next) =>
{
try
{
await next();
}
catch (Exception ex)
{
if (context.Response.HasStarted)
{
throw;
}
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
var json = JToken.FromObject(ex);
await context.Response.WriteAsync(json.ToString());
}
});
//Rest of configure method omitted for brevity.
}
Accept:application/json
不幸的是没有。谢谢,我已经编辑了这个问题以显示新的标题。您的代码是否删除了JsonOutputFormatter
?否,我在对测试控制器get endpoint的有效调用中返回了json。只是不适用于错误消息。这是一个很好的答案。我已经利用了它,它对于我在控制器级别抛出的异常非常有效。然而,在asp核心异常处理中似乎有一个更深层次的问题。我忘了为循环引用对象配置json格式化程序,IActionResult由控制器返回,但在asp核心内,当生成响应时,json格式化程序抛出异常,客户端得到502错误网关响应!最好是获取json序列化异常对象。坏网关在这里毫无意义。你看到这个了吗?解决方法?因此控制器返回一个json结果(还没有异常),当处理该结果时会导致异常。我猜第一种方法不会捕捉到这个,您是否检查过第二种方法是否在这个场景中执行?顺便说一下,当我在内联中间件中手动格式化json时犯了一个愚蠢的错误,我确实看到了502。不知道为什么框架会将它们视为502!我还没有测试场景2,但很快就会测试。真的是502把我吓坏了。如果我们有这样的东西就好了:app.UseJsonExceptionResponses();希望我能在接下来的几天里看看场景2。第二种方法基本上是app.UseJsonExceptionResponses()
,而不创建扩展方法和中间件类:)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Simple error page to avoid a repo dependency.
app.Use(async (context, next) =>
{
try
{
await next();
}
catch (Exception ex)
{
if (context.Response.HasStarted)
{
throw;
}
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
var json = JToken.FromObject(ex);
await context.Response.WriteAsync(json.ToString());
}
});
//Rest of configure method omitted for brevity.
}