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); }