error handling(将ex.Message发送到客户端)

我有一个ASP.NET Core 1.0 Web API应用程序,并尝试弄清楚如果我的控制器调用的函数错误输出exception消息到客户端。

我尝试了很多东西,但没有实现IActionResult

我不明白为什么这不是人们需要的常见事情。 如果真的没有解决方案可以有人告诉我为什么?

我确实使用HttpResponseException(HttpResponseMessage)看到了一些文档,但为了使用它,我必须安装compat shim。 在Core 1.0中有没有新的方法来做这些事情?

这是我一直在尝试垫片,但它不起作用:

 // GET: api/customers/{id} [HttpGet("{id}", Name = "GetCustomer")] public IActionResult GetById(int id) { Customer c = _customersService.GetCustomerById(id); if (c == null) { var response = new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent("Customer doesn't exist", System.Text.Encoding.UTF8, "text/plain"), StatusCode = HttpStatusCode.NotFound }; throw new HttpResponseException(response); //return NotFound(); } return new ObjectResult(c); } 

抛出HttpResponseException ,我查看客户端,无法找到我在内容中发送任何内容的消息。

这是一个简单的错误DTO类

 public class ErrorDto { public int Code {get;set;} public string Message { get; set; } // other fields public override string ToString() { return JsonConvert.SerializeObject(this); } } 

然后使用ExceptionHandler中间件:

  app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { context.Response.StatusCode = 500; // or another Status accordingly to Exception Type context.Response.ContentType = "application/json"; var error = context.Features.Get(); if (error != null) { var ex = error.Error; await context.Response.WriteAsync(new ErrorDto() { Code = , Message = ex.Message // or your custom message // other custom data }.ToString(), Encoding.UTF8); } }); }); 

是的,可以将状态代码更改为您需要的任何内容:

在CustomExceptionFilterAttribute.cs文件中,修改代码如下:

 public class CustomExceptionFilterAttribute : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { var exception = context.Exception; context.Result = new ContentResult { Content = $"Error: {exception.Message}", ContentType = "text/plain", // change to whatever status code you want to send out StatusCode = (int?)HttpStatusCode.BadRequest }; } } 

这就是它。

如果您有自定义exception,那么您也可以在从上下文中获取抛出的exception时检查它们。 接下来,您可以发送不同的HTTP状态代码,代码代码中发生了什么。

希望有所帮助。

您可以创建一个自定义的exceptionfilter,如下所示

 public class CustomExceptionFilterAttribute : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { var exception = context.Exception; context.Result = new JsonResult(exception.Message); } } 

然后将以上属性应用于您的控制器。

 [Route("api/[controller]")] [CustomExceptionFilter] public class ValuesController : Controller { // GET: api/values [HttpGet] public IEnumerable Get() { throw new Exception("Suckers"); return new string[] { "value1", "value2" }; } } 

而不是提出和捕获exception,你如何简化你的行动:

 // GET: api/customers/{id} [HttpGet("{id}", Name = "GetCustomer")] public IActionResult GetById(int id) { var customer = _customersService.GetCustomerById(id); if (customer == null) { return NotFound("Customer doesn't exist"); } return Ok(customer); } 

我写了一篇博客文章 ,其中包含更多选项,例如返回JSON对象而不是文本。

也许这很有帮助。 您可以返回object并发送BadRequest (HTTP CODE:400),并将自定义object作为实际参数发送(我在这里只使用了插值字符串),但您可以输入任何内容。

在您的客户端,您可以捕获该错误情况,例如使用AJAXerror handling程序 。

 // GET: api/TruckFahrerGeoData [HttpGet] public object GetTruckFahrerGeoData() { var truckFahrerGeoDataItems = new List(); var geodataItems = _context.TruckFahrerGeoData; foreach (var truckFahrerGeoData in geodataItems) { GeoTelemetryData geoTelemetryData = JsonConvert.DeserializeObject(truckFahrerGeoData.TelemetryData); if (geoTelemetryData == null) { return BadRequest($"geoTelemetryData null for id: {truckFahrerGeoData.Id}"); } TruckFahrerGeoDataViewModel truckFahrerGeoDataViewModel = new TruckFahrerGeoDataViewModel { Speed = geoTelemetryData.Speed, Accuracy = geoTelemetryData.Accuracy, TruckAppId = geoTelemetryData.Activity.TruckAppId, TruckAuftragStatusId = geoTelemetryData.Activity.TruckAuftragStatusId, ClId = geoTelemetryData.Activity.ClId, TruckAuftragLaufStatusId = geoTelemetryData.Activity.TruckAuftragLaufStatusId, TaskId = geoTelemetryData.Activity.TaskId, TruckAuftragWorkflowStatusId = geoTelemetryData.Activity.TruckAuftragWorkflowStatusId }; truckFahrerGeoDataItems.Add(truckFahrerGeoDataViewModel); } return truckFahrerGeoDataItems; } 

或者像IActionResult那样更清洁的方式:

 // GET: api/TruckFahrerGeoData [HttpGet] public IActionResult GetTruckFahrerGeoData() { var truckFahrerGeoDataItems = new List(); var geodataItems = _context.TruckFahrerGeoData; foreach (var truckFahrerGeoData in geodataItems) { GeoTelemetryData geoTelemetryData = JsonConvert.DeserializeObject(truckFahrerGeoData.TelemetryData); if (geoTelemetryData == null) { return BadRequest($"geoTelemetryData null for id: {truckFahrerGeoData.Id}"); } TruckFahrerGeoDataViewModel truckFahrerGeoDataViewModel = new TruckFahrerGeoDataViewModel { Speed = geoTelemetryData.Speed, Accuracy = geoTelemetryData.Accuracy, TruckAppId = geoTelemetryData.Activity.TruckAppId, TruckAuftragStatusId = geoTelemetryData.Activity.TruckAuftragStatusId, ClId = geoTelemetryData.Activity.ClId, TruckAuftragLaufStatusId = geoTelemetryData.Activity.TruckAuftragLaufStatusId, TaskId = geoTelemetryData.Activity.TaskId, TruckAuftragWorkflowStatusId = geoTelemetryData.Activity.TruckAuftragWorkflowStatusId }; truckFahrerGeoDataItems.Add(truckFahrerGeoDataViewModel); } return Ok(truckFahrerGeoDataItems); }