Best Practice zum Zurückgeben von Fehlern in der ASP.NET-Web-API


384

Ich habe Bedenken hinsichtlich der Art und Weise, wie wir Fehler an den Kunden zurücksenden.

Geben wir den Fehler sofort zurück, indem wir HttpResponseException auslösen, wenn wir einen Fehler erhalten:

public void Post(Customer customer)
{
    if (string.IsNullOrEmpty(customer.Name))
    {
        throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest) 
    }
    if (customer.Accounts.Count == 0)
    {
         throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest) 
    }
}

Oder wir sammeln alle Fehler und senden sie an den Kunden zurück:

public void Post(Customer customer)
{
    List<string> errors = new List<string>();
    if (string.IsNullOrEmpty(customer.Name))
    {
        errors.Add("Customer Name cannot be empty"); 
    }
    if (customer.Accounts.Count == 0)
    {
         errors.Add("Customer does not have any account"); 
    }
    var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
    throw new HttpResponseException(responseMessage);
}

Dies ist nur ein Beispielcode. Es spielt keine Rolle, ob es sich um Validierungsfehler oder Serverfehler handelt. Ich möchte nur die Best Practice sowie die Vor- und Nachteile der einzelnen Ansätze kennen.


1
Siehe stackoverflow.com/a/22163675/200442, das Sie verwenden sollten ModelState.
Daniel Little

1
Beachten Sie, dass die Antworten hier nur Ausnahmen abdecken, die im Controller selbst ausgelöst werden. Wenn Ihre API ein IQueryable <Modell> zurückgibt, das noch nicht ausgeführt wurde, befindet sich die Ausnahme nicht im Controller und wird nicht abgefangen ...
Jess

3
Sehr schöne Frage, aber irgendwie bekomme ich keine Konstruktorüberladung der HttpResponseExceptionKlasse, die zwei in Ihrem Beitrag erwähnte Parameter HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)HttpResponseException(string, HttpStatusCode)
akzeptiert

Antworten:


293

Für mich sende ich normalerweise einen zurück HttpResponseExceptionund setze den Statuscode entsprechend der ausgelösten Ausnahme entsprechend. Wenn die Ausnahme schwerwiegend ist oder nicht, wird bestimmt, ob ich den HttpResponseExceptionsofort zurückschicke .

Letztendlich ist es eine API, die Antworten und keine Ansichten zurücksendet. Ich denke, es ist in Ordnung, eine Nachricht mit der Ausnahme und dem Statuscode an den Verbraucher zurückzusenden. Ich musste derzeit keine Fehler akkumulieren und zurücksenden, da die meisten Ausnahmen normalerweise auf falsche Parameter oder Aufrufe usw. zurückzuführen sind.

Ein Beispiel in meiner App ist, dass der Client manchmal nach Daten fragt, aber keine Daten verfügbar sind. Deshalb werfe ich eine benutzerdefinierte Datei NoDataAvailableExceptionund lasse sie in die Web-API-App sprudeln, wo sie dann in meinem benutzerdefinierten Filter erfasst wird, der sie zurücksendet relevante Nachricht zusammen mit dem richtigen Statuscode.

Ich bin mir nicht 100% sicher, was die beste Vorgehensweise dafür ist, aber das funktioniert derzeit für mich, also mache ich das auch.

Update :

Seit ich diese Frage beantwortet habe, wurden einige Blog-Beiträge zum Thema geschrieben:

https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling

(Dieser hat einige neue Funktionen in den nächtlichen Builds) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi

Update 2

Bei der Aktualisierung unseres Fehlerbehandlungsprozesses gibt es zwei Fälle:

  1. Bei allgemeinen Fehlern wie nicht gefunden oder ungültigen Parametern, die an eine Aktion übergeben werden, wird a zurückgegeben HttpResponseException, um die Verarbeitung sofort zu stoppen. Zusätzlich übergeben wir für Modellfehler in unseren Aktionen das Modellstatuswörterbuch an die Request.CreateErrorResponseErweiterung und verpacken es in a HttpResponseException. Das Hinzufügen des Modellstatuswörterbuchs führt zu einer Liste der Modellfehler, die im Antworttext gesendet werden.

  2. Für Fehler, die in höheren Schichten auftreten, Serverfehler, lassen wir die Ausnahme in die Web-API-App sprudeln. Hier haben wir einen globalen Ausnahmefilter, der die Ausnahme betrachtet, sie mit ELMAH protokolliert und versucht, das richtige HTTP festzulegen Statuscode und eine relevante freundliche Fehlermeldung als Körper wieder in a HttpResponseException. Für Ausnahmen, die wir nicht erwarten, erhält der Client den Standardfehler von 500 internen Servern, aber aus Sicherheitsgründen eine generische Nachricht.

Update 3

Kürzlich haben wir nach dem Aufrufen von Web API 2 zum Zurücksenden allgemeiner Fehler die IHttpActionResult- Schnittstelle verwendet, insbesondere die im System.Web.Http.ResultsNamespace integrierten Klassen wie NotFound, BadRequest, wenn sie passen, wenn wir sie beispielsweise nicht erweitern ein NotFound-Ergebnis mit einer Antwortnachricht:

public class NotFoundWithMessageResult : IHttpActionResult
{
    private string message;

    public NotFoundWithMessageResult(string message)
    {
        this.message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(message);
        return Task.FromResult(response);
    }
}

Vielen Dank für Ihre Antwort geepie, es ist eine gute Erfahrung, also möchten Sie lieber sofort eine Zusendung senden?
Cuongle

Wie gesagt es kommt wirklich auf die Ausnahme an. Eine schwerwiegende Ausnahme, wie zum Beispiel, dass der Benutzer der Web-API einen ungültigen Parameter an einen Endpunkt übergibt. Dann würde ich eine HttpResponseException erstellen und diese sofort an die konsumierende App zurückgeben.
GDP

Die Ausnahmen in der Frage beziehen sich eher auf die Validierung, siehe stackoverflow.com/a/22163675/200442 .
Daniel Little

1
@ DanielLittle Lesen Sie seine Frage noch einmal. Ich zitiere: "Dies ist nur ein Beispielcode, es spielt keine Rolle, ob Validierungsfehler oder
Serverfehler

@gdp Trotzdem gibt es zwei Komponenten: Validierung und Ausnahmen. Daher ist es am besten, beide zu behandeln.
Daniel Little

184

ASP.NET Web API 2 hat es wirklich vereinfacht. Zum Beispiel der folgende Code:

public HttpResponseMessage GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        HttpError err = new HttpError(message);
        return Request.CreateResponse(HttpStatusCode.NotFound, err);
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.OK, item);
    }
}

Gibt den folgenden Inhalt an den Browser zurück, wenn das Element nicht gefunden wird:

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51

{
  "Message": "Product with id = 12 not found"
}

Vorschlag: Wirf keinen HTTP-Fehler 500 aus, es sei denn, es liegt ein katastrophaler Fehler vor (z. B. WCF-Fehlerausnahme). Wählen Sie einen geeigneten HTTP-Statuscode aus, der den Status Ihrer Daten darstellt. (Siehe den Apigee-Link unten.)

Links:


4
Ich würde noch einen Schritt weiter gehen und eine ResourceNotFoundException aus dem DAL / Repo auslösen, die ich im Web Api 2.2 ExceptionHandler auf den Typ ResourceNotFoundException überprüfe, und dann "Produkt mit der ID xxx nicht gefunden" zurückgeben. Auf diese Weise ist es generisch in der Architektur verankert, anstatt bei jeder Aktion.
Pascal

1
Gibt es eine spezifische Verwendung für die return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); Was ist der Unterschied zwischen CreateResponseundCreateErrorResponse
Zapnologica

10
Laut w3.org/Protocols/rfc2616/rfc2616-sec10.html ist ein Clientfehler ein Code mit 400 Ebenen und ein Serverfehler ein Code mit 500 Ebenen. Ein 500-Fehlercode kann daher in vielen Fällen für eine Web-API sehr geeignet sein, nicht nur für "katastrophale" Fehler.
Jess

2
Sie müssen using System.Net.Http;die CreateResponse()Erweiterungsmethode anzeigen.
Adam Szabo

Was mir an der Verwendung von Request.CreateResponse () nicht gefällt, ist, dass unnötige Microsoft-spezifische Serialisierungsinformationen wie "<string xmlns =" schemas.microsoft.com/2003/10/Serialization/">Mein Fehler hier </ string zurückgegeben werden > ". In Situationen, in denen der Status 400 angemessen ist, habe ich festgestellt, dass ApiController.BadRequest (Zeichenfolgenmeldung) eine bessere Zeichenfolge "<Fehler> <Meldung> Mein Fehler hier </ Nachricht> </ Fehler>" zurückgibt. Aber ich kann kein Äquivalent für die Rückgabe des 500-Status mit einer einfachen Nachricht finden.
Vkelman

76

Es sieht so aus, als hätten Sie mehr Probleme mit der Validierung als mit Fehlern / Ausnahmen, daher werde ich zu beiden etwas sagen.

Validierung

Controller-Aktionen sollten im Allgemeinen Eingabemodelle verwenden, bei denen die Validierung direkt im Modell deklariert ist.

public class Customer
{ 
    [Require]
    public string Name { get; set; }
}

Anschließend können Sie eine verwenden ActionFilter, die automatisch Validierungsnachrichten an den Client zurücksendet.

public class ValidationActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid) {
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
        }
    }
} 

Weitere Informationen hierzu finden Sie unter http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc

Fehlerbehandlung

Am besten senden Sie eine Nachricht an den Client zurück, die die aufgetretene Ausnahme darstellt (mit dem entsprechenden Statuscode).

Standardmäßig müssen Sie verwenden, Request.CreateErrorResponse(HttpStatusCode, message)wenn Sie eine Nachricht angeben möchten. Dies bindet den Code jedoch an das RequestObjekt, was Sie nicht tun müssen.

Normalerweise erstelle ich meine eigene Art von "sicherer" Ausnahme, von der ich erwarte, dass der Client weiß, wie er alle anderen mit einem generischen 500-Fehler behandelt und umschließt.

Die Verwendung eines Aktionsfilters zur Behandlung der Ausnahmen würde folgendermaßen aussehen:

public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var exception = context.Exception as ApiException;
        if (exception != null) {
            context.Response = context.Request.CreateErrorResponse(exception.StatusCode, exception.Message);
        }
    }
}

Dann können Sie es global registrieren.

GlobalConfiguration.Configuration.Filters.Add(new ApiExceptionFilterAttribute());

Dies ist mein benutzerdefinierter Ausnahmetyp.

using System;
using System.Net;

namespace WebApi
{
    public class ApiException : Exception
    {
        private readonly HttpStatusCode statusCode;

        public ApiException (HttpStatusCode statusCode, string message, Exception ex)
            : base(message, ex)
        {
            this.statusCode = statusCode;
        }

        public ApiException (HttpStatusCode statusCode, string message)
            : base(message)
        {
            this.statusCode = statusCode;
        }

        public ApiException (HttpStatusCode statusCode)
        {
            this.statusCode = statusCode;
        }

        public HttpStatusCode StatusCode
        {
            get { return this.statusCode; }
        }
    }
}

Eine Beispielausnahme, die meine API auslösen kann.

public class NotAuthenticatedException : ApiException
{
    public NotAuthenticatedException()
        : base(HttpStatusCode.Forbidden)
    {
    }
}

Ich habe ein Problem mit der Fehlerbehandlungsantwort in der ApiExceptionFilterAttribute-Klassendefinition. In der OnException-Methode ist die Ausnahme.StatusCode ungültig, da die Ausnahme eine WebException ist. Was kann ich in diesem Fall tun?
Razp26

1
@ razp26 Wenn Sie sich auf das beziehen var exception = context.Exception as WebException;, was ein Tippfehler war, sollte es gewesen seinApiException
Daniel Little

2
Können Sie bitte ein Beispiel hinzufügen, wie die ApiExceptionFilterAttribute-Klasse verwendet wird?
Razp26

36

Sie können eine HttpResponseException auslösen

HttpResponseMessage response = 
    this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "your message");
throw new HttpResponseException(response);

23

Für Web API 2 geben meine Methoden konsistent IHttpActionResult zurück, also verwende ich ...

public IHttpActionResult Save(MyEntity entity)
{
  ....

    return ResponseMessage(
        Request.CreateResponse(
            HttpStatusCode.BadRequest, 
            validationErrors));
}

Diese Antwort ist in Ordnung, während Sie Verweis aufSystem.Net.Http
Bellash

19

Wenn Sie ASP.NET Web API 2 verwenden, verwenden Sie am einfachsten die ApiController-Kurzmethode. Dies führt zu einem BadRequestResult.

return BadRequest("message");

Streng für Modellvalidierungsfehler verwende ich die Überladung von BadRequest (), die das ModelState-Objekt akzeptiert:return BadRequest(ModelState);
timmi4sa

4

Sie können einen benutzerdefinierten ActionFilter in Web Api verwenden, um das Modell zu überprüfen

public class DRFValidationFilters : ActionFilterAttribute
{

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);

            //BadRequest(actionContext.ModelState);
        }
    }
    public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {

        return Task.Factory.StartNew(() => {

            if (!actionContext.ModelState.IsValid)
            {
                actionContext.Response = actionContext.Request
                     .CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);                    
            }
        });

    }

public class AspirantModel
{
    public int AspirantId { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }        
    public string LastName { get; set; }
    public string AspirantType { get; set; }       
    [RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid Phone number")]
    public string MobileNumber { get; set; }
    public int StateId { get; set; }
    public int CityId { get; set; }
    public int CenterId { get; set; }

}

    [HttpPost]
    [Route("AspirantCreate")]
    [DRFValidationFilters]
    public IHttpActionResult Create(AspirantModel aspirant)
    {
            if (aspirant != null)
            {

            }
            else
            {
                return Conflict();
            }
          return Ok();

}}

Registrieren Sie die CustomAttribute-Klasse in webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());


4

Aufbauend auf Manish Jainder Antwort (die für die Web-API 2 gedacht ist, die die Dinge vereinfacht):

1) Verwenden Sie Validierungsstrukturen, um so viele Validierungsfehler wie möglich zu beantworten. Diese Strukturen können auch verwendet werden, um auf Anfragen aus Formularen zu antworten.

public class FieldError
{
    public String FieldName { get; set; }
    public String FieldMessage { get; set; }
}

// a result will be able to inform API client about some general error/information and details information (related to invalid parameter values etc.)
public class ValidationResult<T>
{
    public bool IsError { get; set; }

    /// <summary>
    /// validation message. It is used as a success message if IsError is false, otherwise it is an error message
    /// </summary>
    public string Message { get; set; } = string.Empty;

    public List<FieldError> FieldErrors { get; set; } = new List<FieldError>();

    public T Payload { get; set; }

    public void AddFieldError(string fieldName, string fieldMessage)
    {
        if (string.IsNullOrWhiteSpace(fieldName))
            throw new ArgumentException("Empty field name");

        if (string.IsNullOrWhiteSpace(fieldMessage))
            throw new ArgumentException("Empty field message");

        // appending error to existing one, if field already contains a message
        var existingFieldError = FieldErrors.FirstOrDefault(e => e.FieldName.Equals(fieldName));
        if (existingFieldError == null)
            FieldErrors.Add(new FieldError {FieldName = fieldName, FieldMessage = fieldMessage});
        else
            existingFieldError.FieldMessage = $"{existingFieldError.FieldMessage}. {fieldMessage}";

        IsError = true;
    }

    public void AddEmptyFieldError(string fieldName, string contextInfo = null)
    {
        AddFieldError(fieldName, $"No value provided for field. Context info: {contextInfo}");
    }
}

public class ValidationResult : ValidationResult<object>
{

}

2) Die Serviceschicht gibt ValidationResults zurück, unabhängig davon, ob der Vorgang erfolgreich ist oder nicht. Z.B:

    public ValidationResult DoSomeAction(RequestFilters filters)
    {
        var ret = new ValidationResult();

        if (filters.SomeProp1 == null) ret.AddEmptyFieldError(nameof(filters.SomeProp1));
        if (filters.SomeOtherProp2 == null) ret.AddFieldError(nameof(filters.SomeOtherProp2 ), $"Failed to parse {filters.SomeOtherProp2} into integer list");

        if (filters.MinProp == null) ret.AddEmptyFieldError(nameof(filters.MinProp));
        if (filters.MaxProp == null) ret.AddEmptyFieldError(nameof(filters.MaxProp));


        // validation affecting multiple input parameters
        if (filters.MinProp > filters.MaxProp)
        {
            ret.AddFieldError(nameof(filters.MinProp, "Min prop cannot be greater than max prop"));
            ret.AddFieldError(nameof(filters.MaxProp, "Check"));
        }

        // also specify a global error message, if we have at least one error
        if (ret.IsError)
        {
            ret.Message = "Failed to perform DoSomeAction";
            return ret;
        }

        ret.Message = "Successfully performed DoSomeAction";
        return ret;
    }

3) Der API-Controller erstellt die Antwort basierend auf dem Ergebnis der Servicefunktion

Eine Möglichkeit besteht darin, praktisch alle Parameter als optional festzulegen und eine benutzerdefinierte Validierung durchzuführen, die eine aussagekräftigere Antwort liefert. Außerdem achte ich darauf, dass keine Ausnahme über die Servicegrenze hinausgeht.

    [Route("DoSomeAction")]
    [HttpPost]
    public HttpResponseMessage DoSomeAction(int? someProp1 = null, string someOtherProp2 = null, int? minProp = null, int? maxProp = null)
    {
        try
        {
            var filters = new RequestFilters 
            {
                SomeProp1 = someProp1 ,
                SomeOtherProp2 = someOtherProp2.TrySplitIntegerList() ,
                MinProp = minProp, 
                MaxProp = maxProp
            };

            var result = theService.DoSomeAction(filters);
            return !result.IsError ? Request.CreateResponse(HttpStatusCode.OK, result) : Request.CreateResponse(HttpStatusCode.BadRequest, result);
        }
        catch (Exception exc)
        {
            Logger.Log(LogLevel.Error, exc, "Failed to DoSomeAction");
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, new HttpError("Failed to DoSomeAction - internal error"));
        }
    }

3

Verwenden Sie die integrierte Methode "InternalServerError" (verfügbar in ApiController):

return InternalServerError();
//or...
return InternalServerError(new YourException("your message"));

0

Nur um den aktuellen Status von ASP.NET WebAPI zu aktualisieren. Die Schnittstelle wird jetzt aufgerufen IActionResultund die Implementierung hat sich nicht wesentlich geändert:

[JsonObject(IsReference = true)]
public class DuplicateEntityException : IActionResult
{        
    public DuplicateEntityException(object duplicateEntity, object entityId)
    {
        this.EntityType = duplicateEntity.GetType().Name;
        this.EntityId = entityId;
    }

    /// <summary>
    ///     Id of the duplicate (new) entity
    /// </summary>
    public object EntityId { get; set; }

    /// <summary>
    ///     Type of the duplicate (new) entity
    /// </summary>
    public string EntityType { get; set; }

    public Task ExecuteResultAsync(ActionContext context)
    {
        var message = new StringContent($"{this.EntityType ?? "Entity"} with id {this.EntityId ?? "(no id)"} already exist in the database");

        var response = new HttpResponseMessage(HttpStatusCode.Ambiguous) { Content = message };

        return Task.FromResult(response);
    }

    #endregion
}

Das sieht interessant aus, aber wo genau im Projekt ist dieser Code platziert? Ich mache mein Web-API-2-Projekt in vb.net.
Aus dem Gold

Es ist nur ein Modell für die Rückgabe des Fehlers und kann sich überall befinden. Sie würden eine neue Instanz der oben genannten Klasse in Ihrem Controller zurückgeben. Aber um ehrlich zu sein, versuche ich, wann immer möglich, die eingebauten Klassen zu verwenden: this.Ok (), CreatedAtRoute (), NotFound (). Die Signatur der Methode wäre IHttpActionResult. Ich weiß nicht, ob sie das alles mit NetCore geändert haben
Thomas Hagström

-2

Bei Fehlern, bei denen modelstate.isvalid false ist, sende ich den Fehler im Allgemeinen so, wie er vom Code ausgelöst wird. Es ist leicht zu verstehen für den Entwickler, der meinen Service in Anspruch nimmt. Normalerweise sende ich das Ergebnis mit dem folgenden Code.

     if(!ModelState.IsValid) {
                List<string> errorlist=new List<string>();
                foreach (var value in ModelState.Values)
                {
                    foreach(var error in value.Errors)
                    errorlist.Add( error.Exception.ToString());
                    //errorlist.Add(value.Errors);
                }
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest,errorlist);}

Dadurch wird der Fehler im folgenden Format an den Client gesendet. Dies ist im Grunde eine Liste von Fehlern:

    [  
    "Newtonsoft.Json.JsonReaderException: **Could not convert string to integer: abc. Path 'Country',** line 6, position 16.\r\n   
at Newtonsoft.Json.JsonReader.ReadAsInt32Internal()\r\n   
at Newtonsoft.Json.JsonTextReader.ReadAsInt32()\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter, Boolean inArray)\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)",

       "Newtonsoft.Json.JsonReaderException: **Could not convert string to integer: ab. Path 'State'**, line 7, position 13.\r\n   
at Newtonsoft.Json.JsonReader.ReadAsInt32Internal()\r\n   
at Newtonsoft.Json.JsonTextReader.ReadAsInt32()\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter, Boolean inArray)\r\n   
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)"
    ]

Ich würde nicht empfehlen, diese Detailebene in der Ausnahme zurückzusenden, wenn dies eine externe API wäre (dh dem öffentlichen Internet ausgesetzt wäre). Sie sollten den Filter weiter bearbeiten und ein JSON-Objekt (oder XML, wenn dies das gewählte Format ist) zurücksenden, in dem der Fehler und nicht nur ein ToString der Ausnahme aufgeführt sind.
Sudhanshu Mishra

Richtig, diese Ausnahme wurde nicht für die externe API gesendet. Sie können es jedoch zum Debuggen von Problemen in der internen API und während des Testens verwenden.
Ashish Sahu
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.