如何从ASP返回HTTP 500。NET Core RC2 Web Api?

在RC1中,我会这样做:

[HttpPost]
public IActionResult Post([FromBody]string something)
{
try{
// ...
}
catch(Exception e)
{
return new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError);
}
}

在RC2中,不再有HttpStatusCodeResult,并且没有任何东西可以让我返回一个500类型的IActionResult。

现在的方法与我要求的完全不同吗?在Controller代码中不再尝试catch吗?我们只是让框架向API调用者抛出一个通用的500异常吗?对于开发,我如何才能看到确切的异常堆栈?

320217 次浏览

从我所看到的ControllerBase类中有helper方法。只需使用StatusCode方法:

[HttpPost]
public IActionResult Post([FromBody] string something)
{
//...
try
{
DoSomething();
}
catch(Exception e)
{
LogException(e);
return StatusCode(500);
}
}

你也可以使用StatusCode(int statusCode, object value)重载来协商内容。

如果你不希望硬编码特定的数字,你可以使用Microsoft.AspNetCore.Mvc.ControllerBase.StatusCodeMicrosoft.AspNetCore.Http.StatusCodes来形成你的响应。

return  StatusCode(StatusCodes.Status500InternalServerError);

更新:2019年8月

也许与最初的问题没有直接关系,但当试图用Microsoft Azure Functions实现相同的结果时,我发现我必须在Microsoft.AspNetCore.Mvc.Core程序集中构造一个新的StatusCodeResult对象。我的代码现在是这样的;

return new StatusCodeResult(StatusCodes.Status500InternalServerError);
return StatusCode((int)HttpStatusCode.InternalServerError, e);

应用于非asp。NET上下文(参见ASP. NET上下文的其他答案)。网络核心)。

HttpStatusCodeSystem.Net中的一个枚举。

目前(1.1)更好的处理方法是在Startup.csConfigure()中这样做:

app.UseExceptionHandler("/Error");

这将执行/Error的路由。这将使您不必为编写的每个操作添加try-catch块。

当然,你需要添加一个类似这样的ErrorController:

[Route("[controller]")]
public class ErrorController : Controller
{
[Route("")]
[AllowAnonymous]
public IActionResult Get()
{
return StatusCode(StatusCodes.Status500InternalServerError);
}
}

更多信息在这里


如果你想要得到实际的异常数据,你可以把它添加到上面的Get()语句之前的return语句。

// Get the details of the exception that occurred
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();


if (exceptionFeature != null)
{
// Get which route the exception occurred at
string routeWhereExceptionOccurred = exceptionFeature.Path;


// Get the exception that occurred
Exception exceptionThatOccurred = exceptionFeature.Error;


// TODO: Do something with the exception
// Log it with Serilog?
// Send an e-mail, text, fax, or carrier pidgeon?  Maybe all of the above?
// Whatever you do, be careful to catch any exceptions, otherwise you'll end up with a blank page and throwing a 500
}

以上片段取自斯科特·索伯的博客

如何创建一个自定义ObjectResult类,它表示一个内部服务器错误,就像OkObjectResult那样? 你可以在你自己的基类中放置一个简单的方法,这样你就可以很容易地生成InternalServerError并返回它,就像你做Ok()BadRequest()一样
[Route("api/[controller]")]
[ApiController]
public class MyController : MyControllerBase
{
[HttpGet]
[Route("{key}")]
public IActionResult Get(int key)
{
try
{
//do something that fails
}
catch (Exception e)
{
LogException(e);
return InternalServerError();
}
}
}


public class MyControllerBase : ControllerBase
{
public InternalServerErrorObjectResult InternalServerError()
{
return new InternalServerErrorObjectResult();
}


public InternalServerErrorObjectResult InternalServerError(object value)
{
return new InternalServerErrorObjectResult(value);
}
}


public class InternalServerErrorObjectResult : ObjectResult
{
public InternalServerErrorObjectResult(object value) : base(value)
{
StatusCode = StatusCodes.Status500InternalServerError;
}


public InternalServerErrorObjectResult() : this(null)
{
StatusCode = StatusCodes.Status500InternalServerError;
}
}

如果你需要一个人来回应,你可以打电话

return StatusCode(StatusCodes.Status500InternalServerError, responseObject);

这将返回一个500和响应对象…

当你想在MVC .Net Core中返回JSON响应时,你也可以使用:

Response.StatusCode = (int)HttpStatusCode.InternalServerError;//Equals to HTTPResponse 500
return Json(new { responseText = "my error" });

这将返回JSON结果和HTTPStatus。我用它来返回结果到jQuery.ajax()。

对于aspnetcore-3.1,你也可以像下面这样使用Problem();

https://learn.microsoft.com/en-us/aspnet/core/web-api/handle-errors?view=aspnetcore-3.1

 [Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
[FromServices] IWebHostEnvironment webHostEnvironment)
{
if (webHostEnvironment.EnvironmentName != "Development")
{
throw new InvalidOperationException(
"This shouldn't be invoked in non-development environments.");
}


var context = HttpContext.Features.Get<IExceptionHandlerFeature>();


return Problem(
detail: context.Error.StackTrace,
title: context.Error.Message);
}

Microsoft.AspNetCore.Mvc的内置Problem()方法将返回一个基于RFC 7807的“问题细节”-response(在ASP. aspnetcore . mvc中)。NET Core 3.0及更高版本)。只要没有显式地设置其他状态,它将始终返回状态代码500。

[HttpPost]
public IActionResult Post([FromBody] string value)
{
try
{
// ...
}
catch (Exception ex)
{
return Problem(
//all parameters are optional:
//detail: "Error while processing posted data."; //an explanation, ex.Stacktrace, ...
//instance: "/city/London"  //A reference that identifies the specific occurrence of the problem
//title: "An error occured." //a short title, maybe ex.Message
//statusCode: StatusCodes.Status504GatewayTimeout, //will always return code 500 if not explicitly set
//type: "http://example.com/errors/error-123-details"  //a reference to more information
);
}
}

如果不设置任何参数,它将返回:

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
"title": "An error occured while processing your request.",
"status": 500,
"traceId": "|fadaed95-4d06eb16160e4996."
}

更多关于“问题细节”的信息;参数: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.problemdetails?view=aspnetcore-5.0 < / p >

对于API响应(使用net core),我已经尝试过了,似乎工作得很好:

var err = Content(JsonConvert.SerializeObject(response, SerializerSettings), "application/x-javascript", contentEncoding: System.Text.Encoding.UTF8);
err.StatusCode = StatusCodes.Status500InternalServerError;
return err;

您只需要首先创建一个响应对象,然后响应这个。这样做,我们可以保留内容类型、编码,并添加状态代码。

只是添加这个供将来参考,谁是卡在以及想要一个快速和简单的方法来做到这一点。