2016-03-09 5 views
6

Die Steuerung Vorlage WebAPI in MVC6/WebAPI implementiert eine Aktion, die eine Kollektion für die Get-Methode wie folgt zurück:Rückkehr Fehlerstring aus MVC6/WepApi Controller

[HttpGet] 
public IEnumerable<MyEntity> Get() 
{ 
    //my code to return entities 
} 

Unter der Annahme, dass mein Code das Ergebnis wirft eine zurückzukehren Ausnahme, wie würde ich eine Fehlermeldung an den Verbraucher zurückgeben?

Soweit ich bemerkte eine Ausnahme würde HTTP 500 ergeben. Das ist in Ordnung, aber ich möchte dem Anrufer eine Nachricht sagen, was schief gelaufen ist. Wegen der Signatur der Template-Aktion kann ich die Ausnahme nicht abfangen und einige Http *** oder ObjectResult Instanz zurückgeben.

+0

Werfen Sie einen Blick auf den Antworten auf [dieser] (http://stackoverflow.com/q/31054012/5233410) Frage – Nkosi

Antwort

10

Sie müssen selbst ein Stück Code hinzufügen, das Fehler behandelt und eine Nachricht zurückgibt.

Eine Option besteht darin, einen Ausnahmefilter zu verwenden und ihn entweder global oder auf ausgewählten Controllern hinzuzufügen, obwohl dieser Ansatz nur Ausnahmen abdecken würde, die von den Controller-Aktionsmethoden kommen. Zum Beispiel werden die folgenden Filter ein Json-Objekt zurück nur, wenn die Anforderung akzeptieren war application/json (Sonst wäre es die Ausnahme passieren lassen, durch die beispielsweise durch die globale Fehlerseite behandelt werden könnte):

public class CustomJSONExceptionFilter : ExceptionFilterAttribute 
{  
    public override void OnException(ExceptionContext context) 
    { 
     if (context.HttpContext.Request.GetTypedHeaders().Accept.Any(header => header.MediaType == "application/json")) 
     { 
      var jsonResult = new JsonResult(new { error = context.Exception.Message }); 
      jsonResult.StatusCode = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError; 
      context.Result = jsonResult; 
     } 
    } 
} 

services.AddMvc(opts => 
{ 
    //Here it is being added globally. 
    //Could be used as attribute on selected controllers instead 
    opts.Filters.Add(new CustomJSONExceptionFilter()); 
}); 

Eine weitere Option Sie können die Signatur ändern, um flexibler zu reagieren. Dann können Sie den Fehler so behandeln, wie normalerweise, und dann eine benutzerfreundliche Fehlermeldung zurückgeben.

public IActionResult Get() { 
    try { 
     IEnumerable<MyEntity> result; 
     //...result populated 
     return new HttpOkObjectResult(result); 
    } catch (Exception ex) { 
     //You should handle the error 
     HandleError(ex);//the is not an actual method. Create your own. 
     //You could then create your own error so as not to leak 
     //internal information. 
     var error = new 
      { 
       message = "Enter you user friendly error message", 
       status = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError 
      }; 
     Context.Response.StatusCode = error.status;    
     return new ObjectResult(error); 
    } 
} 
+1

Zusammen mit dem von Ihnen bereitgestellten Link können Sie drei verschiedene Möglichkeiten nutzen. Ich werde sehen, was am besten passt. Ich werde deine Antwort akzeptieren! – NicolasR

1

Genau wie Sie würden jedes Programm laufen lassen.

try { 
    ... 
} catch (Exception e) { 
    return errorMessageView; 
} 

Alternativ können Sie die HandleErrorAttribute verwenden.

+0

Danke, aber ich glaube, ich wasn‘ t klar genug. Ich schreibe eine API, also möchte ich keine Ansicht zurückgeben. Der Client sollte nach Http OK (200) oder 500 (interner Fehler) suchen. Falls der Client 500 hat, sollte er eine Fehlermeldung anzeigen können. Wie bekomme ich diese Fehlermeldung vom Exception-Handler zum Client? Nach HandleErrorAttribute suchen Ich habe HttpResponseException gefunden, aber dies scheint in MVC 6 nicht unterstützt zu werden. – NicolasR

+0

können Sie JSON '{'result': 'error', 'status', 500}' 'zurückgeben? – will

+0

Nur wenn ich die return-Anweisung ändere, aber das fühlt sich unnatürlich an, weil die Controller-Vorlage immer Get-Aktionen mit wiederkehrenden Collections erzeugt. Von dem, was andere vorgeschlagen haben, sieht es am besten aus, die Ausnahme durchzulassen und eine Filter- oder Fehler-Middleware zu implementieren. – NicolasR

3

Ihre Methode ändern, um wie

[HttpGet] 
[ResponseType(typeof(IEnumerable<MyEntity>))] 
public IHttpActionResult Get() 
{ 
    //when ok 
    return Ok(response); // response is your IEnumerable<MyEntity> 

    //when error 
    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.WhateverStatusCodeSuitable) 
      { 
       ReasonPhrase = "your message" 
      }); 

} 
+2

Sieht gut aus, aber wie in diesem Post http://stackoverflow.com/questions/31054012/asp-net-5-mvc-6-equivalent-of-httpexception?lq=1 HttpResponseException ist nicht mehr verfügbar. – NicolasR

0

Sie können Kampf mit Ausnahmen, aber ich habe den Eindruck, wir sind nicht so mehr denken soll. Dies scheint die zen von MVC6 zu sein:

[HttpGet("{id}")] 
    [ProducesResponseType(typeof(IEnumerable<string>), 200)] 
    [ProducesResponseType(typeof(void), 404)] 
    public IActionResult Get(int id) 
    { 
     Product product = null; 
     if (!this.productRepository.TryGet(id, out product)) 
     { 
      return NotFound(); 
     } 

     return Ok(product); 
    } 
+0

Wenn es nur um gefunden oder nicht gefunden wurde, dann ok.Aber was ist mit all den tatsächlichen Ausnahmen, die in realistischen Szenarios vorkommen, wie einer beschädigten Datenbank, nicht verfügbaren verschachtelten Diensten und, nicht zu vergessen, von Programmierern eingeführten Fehlern. Ich stimme zu, dass IActionResult mir die Freiheit geben würde, alles zurückzugeben, was benötigt wird, aber das würde bedeuten, dass ich Ausnahmen in jeder Controller-Methode abfangen musste, um sie in etwas wie "Ein Fehler ist aufgetreten, bitte konsultieren ..." umzuwandeln). – NicolasR

+0

Ob Sie es mögen oder nicht, all diese Ausnahmen werden in HTTP-Ergebnisse der einen oder anderen Form umgewandelt. Dies, IMO, erfasst gerade dieses Paradigma, anstatt die Illusion zu geben, dass eine Ausnahme tatsächlich an den Client zurückgegeben wird. –

+0

Ich stimme mit Ihnen überein über das Paradigma und ich benutze Code wie Sie in den meisten meiner Methoden veröffentlicht. Auf der anderen Seite sehen Sie sich das zweite Code-Snippet in der Antwort von Nkosi an. Ich möchte wirklich keinen Code in jedem meiner Controller haben. Mein Problem ist, dass der Standard-Ausnahme-Handler Code 500 nur ohne Fehlertext an den Client zurückgibt. Deshalb mag ich die CustomExceptionFilter-Lösung. – NicolasR

Verwandte Themen