try tipos que propiedades mensaje las existen excepciones errores error crear como catch capturar c# asp.net asp.net-web-api asp.net-core asp.net-core-1.0

c# - tipos - Manejo de errores(envío de un mensaje al cliente)



tipos de excepciones en c# (6)

Tengo una aplicación ASP.NET Core 1.0 Web API y estoy tratando de descubrir cómo pasar el mensaje de excepción al cliente si una función que mi controlador está llamando errores.

He intentado muchas cosas, pero nada implementa IActionResult .

No entiendo por qué esto no es algo común que la gente necesita. Si realmente no hay solución, ¿alguien puede decirme por qué?

Veo algo de documentación por ahí usando HttpResponseException(HttpResponseMessage) , pero para usar esto, tengo que instalar la compatibilidad shim. ¿Hay una nueva forma de hacer estas cosas en Core 1.0?

Aquí hay algo que he estado intentando con la cuña pero no funciona:

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

Cuando se lanza la HttpResponseException , miro al cliente y no puedo encontrar el mensaje que estoy enviando nada en el contenido.


Aquí hay un error simple clase DTO

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

Y luego usando el middleware 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<IExceptionHandlerFeature>(); if (error != null) { var ex = error.Error; await context.Response.WriteAsync(new ErrorDto() { Code = <your custom code based on Exception Type>, Message = ex.Message // or your custom message // other custom data }.ToString(), Encoding.UTF8); } }); });


En lugar de plantear y atrapar una excepción, ¿qué tal si simplifica su acción para:

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

Escribí una publicación de blog con algunas opciones más, como devolver un objeto JSON en lugar de texto.


Puede crear un filtro de excepción personalizado como a continuación

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

Luego aplique el atributo anterior a su controlador.

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


Quizás eso sea útil. Puede devolver solo un object y enviar, por ejemplo, un BadRequest (CÓDIGO HTTP: 400) con su object personalizado como parámetro real (acabo de usar una cadena interpolada aquí) pero puede poner cualquier cosa.

En su lado del cliente, puede detectar esa situación de error, por ejemplo, con un controlador de errores AJAX .

// GET: api/TruckFahrerGeoData [HttpGet] public object GetTruckFahrerGeoData() { var truckFahrerGeoDataItems = new List<TruckFahrerGeoDataViewModel>(); var geodataItems = _context.TruckFahrerGeoData; foreach (var truckFahrerGeoData in geodataItems) { GeoTelemetryData geoTelemetryData = JsonConvert.DeserializeObject<GeoTelemetryData>(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; }

O una forma aún más limpia con IActionResult así:

// GET: api/TruckFahrerGeoData [HttpGet] public IActionResult GetTruckFahrerGeoData() { var truckFahrerGeoDataItems = new List<TruckFahrerGeoDataViewModel>(); var geodataItems = _context.TruckFahrerGeoData; foreach (var truckFahrerGeoData in geodataItems) { GeoTelemetryData geoTelemetryData = JsonConvert.DeserializeObject<GeoTelemetryData>(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); }


Sí, es posible cambiar el código de estado a lo que necesite:

En su archivo CustomExceptionFilterAttribute.cs, modifique el código de la siguiente manera:

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

Eso es practicamente todo.

Si tiene excepciones personalizadas, también puede verificarlas al obtener la excepción lanzada del contexto. Después de eso, puede enviar diferentes códigos de estado HTTP según lo que sucedió en su código.

Espero que ayude.


Tuve el mismo problema y después de investigar un poco, descubrí que podía usar HttpClient para llamar a mi API y leer la respuesta fácilmente. HttpClient no arroja ningún error cuando la respuesta HTTP contiene un código de error, pero establece la propiedad IsSuccessStatusCode en falso.

Esta es mi función usando el HttpClient. Llamo a esto desde mi controlador.

public static async Task<HttpResponseMessage> HttpClientPost(string header, string postdata, string url) { string uri = apiUrl + url; using (var client = new HttpClient()) { //client.BaseAddress = new Uri(uri); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", header); HttpResponseMessage response = await client.PostAsync(uri, new StringContent(postdata)); return response; } }

Este es mi código de controlador, donde llamo a la función y leo la respuesta y determino si tengo un error o no y respondo en consecuencia. Tenga en cuenta que estoy comprobando el IsSuccessStatusCode.

HttpResponseMessage response; string url = $"Setup/AddDonor"; var postdata = JsonConvert.SerializeObject(donor); response = await ApiHandler.HttpClientPost(HttpContext.Session.GetString(tokenName), postdata, url); //var headers = response.Headers.Concat(response.Content.Headers); var responseBody = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { tnxresult = JsonConvert.DeserializeObject<TnxResult>(AppFunctions.CleanResponse(responseBody)); return Json(new { ok = true, message = tnxresult.Message, statusCode = tnxresult.StatusCode }); } else { ApiError rs = JsonConvert.DeserializeObject<ApiError>(AppFunctions.CleanResponse(responseBody)); return Json(new { ok = false, message = rs.Message, statusCode = rs.StatusCode }); }

Mi API devuelve mensajes de error en JSON. Si la llamada es exitosa, también estoy empaquetando la respuesta en JSON.

La línea de código crucial es esta ...

var responseBody = await response.Content.ReadAsStringAsync();

Serializa el contenido HTTP en una cadena como una operación asincrónica.

Después de eso, puedo convertir mi cadena JSON en un objeto y acceder al mensaje de error / éxito y también al Código de estado.