42 votes

Traitement des erreurs (envoi d'un message ex. Au client)

J'ai un ASP.NET Core 1.0 de l'API Web de l'application et essayer de comprendre comment passer le message de l'exception pour le client si une fonction que mon contrôleur est l'appel d'erreurs.

J'ai essayé beaucoup de choses, mais rien n'implémente IActionResult.

Je ne comprends pas pourquoi ce n'est pas une chose commune que les gens ont besoin. Si il n'est véritablement pas une solution, quelqu'un peut-il me dire pourquoi?

Je vois une partie de la documentation là à l'aide de HttpResponseException(HttpResponseMessage), mais pour les utiliser de cette manière, je dois installer le compat cale. Est-il une nouvelle façon de faire ces choses en Core 1.0?

Voici quelque chose que j'ai essayé avec la cale, mais il ne fonctionne pas:

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

Lorsque l' HttpResponseException est jeté, je regarde sur le client et ne peut pas trouver le message, je suis envoyer quoi que ce soit dans le contenu.

60voto

Set Points 21500

Voici une simple classe DTO d'erreur

 public class ErrorDto
{
    public int Code {get;set;}
    public string Message { get; set; }

    // other fields

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}
 

Et puis en utilisant le 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);
                    }
                });
            });
 

9voto

shabbirh Points 330

Oui, il est possible de changer le code de statut en ce dont vous avez besoin:

Dans votre fichier CustomExceptionFilterAttribute.cs, modifiez le code comme suit:

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

C'est à peu près ça.

Si vous avez des exceptions personnalisées, vous pouvez également les vérifier lors de la récupération de l'exception levée à partir du contexte. Suite à cela, vous pouvez ensuite envoyer différents codes d'état HTTP en fonction de ce qui s'est passé dans votre code.

J'espère que cela pourra aider.

6voto

cvraman Points 1529

Vous pouvez créer un filtre d'exception personnalisé comme ci-dessous

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

Appliquez ensuite l'attribut ci-dessus à votre contrôleur.

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

5voto

Paul Hiles Points 3887

Plutôt que de lever et d'attraper une exception, que diriez-vous de simplifier votre action pour:

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

J'ai écrit un article de blog avec d'autres options telles que le retour d'un objet JSON au lieu de texte.

1voto

Eric Brunner Points 155

Peut-être que c'est utile. Vous pouvez revenir juste d' object et envoyés, par exemple, un BadRequest (CODE HTTP: de 400) avec votre coutume object comme paramètre réel (j'ai juste utilisé une interpolation de chaîne ici) mais vous pouvez le mettre dans n'importe quoi.

De votre côté client, vous pouvez intercepter cette situation d'erreur par exemple avec un AJAX gestionnaire d'erreur.

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

Ou encore plus le moyen le plus propre avec IActionResult de cette manière:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X