Mam wątpliwości dotyczące sposobu, w jaki zwracamy błędy klientowi.
Czy zwracamy błąd natychmiast, zgłaszając wyjątek HttpResponseException, gdy pojawia się błąd:
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)
}
}
Lub gromadzimy wszystkie błędy, a następnie odsyłamy do klienta:
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);
}
To tylko przykładowy kod, nie ma znaczenia ani błąd sprawdzania poprawności, ani błąd serwera, chciałbym tylko poznać najlepsze praktyki, zalety i wady każdego podejścia.
c#
rest
asp.net-web-api
cuongle
źródło
źródło
ModelState
.HttpResponseException
klasę, która bierze dwa parametry wymienione w twoim poście -HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
tj.HttpResponseException(string, HttpStatusCode)
Odpowiedzi:
Dla mnie zazwyczaj wysyłam zwrot
HttpResponseException
i ustawiam kod statusu odpowiednio w zależności od zgłoszonego wyjątku, a jeśli wyjątek jest krytyczny, czy nie, zdecyduję, czy odHttpResponseException
razu go odesłam.Pod koniec dnia jest to interfejs API wysyłający odpowiedzi, a nie widoki, więc myślę, że w porządku jest odesłanie konsumentowi wiadomości z wyjątkiem i kodem statusu. Obecnie nie muszę kumulować błędów i odsyłać je z powrotem, ponieważ większość wyjątków wynika zwykle z niepoprawnych parametrów lub połączeń itp.
Przykładem w mojej aplikacji jest to, że czasami klient prosi o dane, ale dane nie są dostępne, więc rzucam niestandardowy
NoDataAvailableException
i pozwalam na bąbelkowanie do aplikacji interfejsu API sieci Web, gdzie następnie w moim niestandardowym filtrze, który przechwytuje odesłanie odpowiedni komunikat wraz z poprawnym kodem statusu.Nie jestem w 100% pewien, jaka jest najlepsza praktyka w tym zakresie, ale obecnie działa to dla mnie, więc to właśnie robię.
Aktualizacja :
Od kiedy odpowiedziałem na to pytanie, na ten temat napisano kilka postów na blogu:
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(ten ma kilka nowych funkcji w nocnych kompilacjach) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
Aktualizacja 2
Zaktualizuj nasz proces obsługi błędów, mamy dwa przypadki:
W przypadku ogólnych błędów, takich jak nie znaleziono lub niepoprawnych parametrów przekazywanych do akcji zwracamy a,
HttpResponseException
aby natychmiast przerwać przetwarzanie. Dodatkowo za błędy modelu w naszych działaniach przekażemy słownik stanu modeluRequest.CreateErrorResponse
rozszerzeniu i zawiniemy go wHttpResponseException
. Dodanie słownika stanu modelu powoduje wyświetlenie listy błędów modelu wysłanych w treści odpowiedzi.W przypadku błędów, które występują w wyższych warstwach, błędów serwera, pozwalamy wyjątkowi na bąbelkowanie aplikacji Web API, tutaj mamy globalny filtr wyjątków, który patrzy na wyjątek, rejestruje go za pomocą ELMAH i próbuje znaleźć sens, ustawiając poprawny HTTP kod statusu i odpowiedni przyjazny komunikat o błędzie jako treść ponownie w
HttpResponseException
. Z wyjątkami, których nie oczekujemy, klient otrzyma domyślny błąd wewnętrzny serwera 500, ale ogólny komunikat ze względów bezpieczeństwa.Aktualizacja 3
Ostatnio, po podniesieniu Web API 2, do odesłania ogólnych błędów używamy teraz interfejsu IHttpActionResult , a konkretnie wbudowanych klas w
System.Web.Http.Results
przestrzeni nazw, takich jak NotFound, BadRequest, gdy pasują, jeśli nie rozszerzamy ich, na przykład wynik NotFound z komunikatem odpowiedzi:źródło
Interfejs API sieci Web ASP.NET 2 naprawdę go uprościł. Na przykład następujący kod:
zwraca następującą treść do przeglądarki, gdy element nie zostanie znaleziony:
Sugestia: Nie zgłaszaj błędu HTTP 500, chyba że wystąpi błąd katastroficzny (na przykład wyjątek błędu WCF). Wybierz odpowiedni kod stanu HTTP, który reprezentuje stan twoich danych. (Zobacz poniższy link apigee.)
Spinki do mankietów:
źródło
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
Czym jest różnica międzyCreateResponse
iCreateErrorResponse
using System.Net.Http;
wyświetlićCreateResponse()
metodę rozszerzenia.Wygląda na to, że masz więcej problemów z walidacją niż błędy / wyjątki, więc powiem trochę o obu.
Uprawomocnienie
Działania kontrolera powinny zasadniczo przyjmować modele wejściowe, w których sprawdzanie poprawności jest zadeklarowane bezpośrednio w modelu.
Następnie możesz użyć narzędzia,
ActionFilter
które automatycznie wysyła wiadomości sprawdzające poprawność z powrotem do klienta.Aby uzyskać więcej informacji na ten temat, sprawdź http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Obsługa błędów
Najlepiej jest zwrócić klientowi wiadomość, która reprezentuje wyjątek, który się wydarzył (z odpowiednim kodem stanu).
Po wyjęciu z pudełka musisz użyć,
Request.CreateErrorResponse(HttpStatusCode, message)
jeśli chcesz określić wiadomość. Powoduje to jednak powiązanie kodu zRequest
obiektem, co nie powinno być konieczne.Zwykle tworzę własny typ „bezpiecznego” wyjątku, który, jak się spodziewam, wiedziałby, że klient będzie wiedział, jak obsłużyć i zawinąć wszystkie inne z ogólnym błędem 500.
Użycie filtra akcji do obsługi wyjątków wyglądałoby następująco:
Następnie możesz zarejestrować go globalnie.
To jest mój niestandardowy typ wyjątku.
Przykład wyjątku, który może wygenerować mój interfejs API.
źródło
var exception = context.Exception as WebException;
że to była literówka, powinno byćApiException
Możesz zgłosić wyjątek HttpResponseException
źródło
W przypadku Web API 2 moje metody konsekwentnie zwracają IHttpActionResult, więc używam ...
źródło
System.Net.Http
Jeśli korzystasz z ASP.NET Web API 2, najprostszym sposobem jest użycie krótkiej metody ApiController. Spowoduje to BadRequestResult.
źródło
return BadRequest(ModelState);
możesz użyć niestandardowego filtru ActionFilter w interfejsie WWW, aby sprawdzić poprawność modelu
}
Zarejestruj klasę CustomAttribute w webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());
źródło
Opierając się na
Manish Jain
odpowiedzi (która jest przeznaczona dla Web API 2, który upraszcza rzeczy):1) Użyj struktur sprawdzania poprawności, aby zareagować na jak najwięcej błędów sprawdzania poprawności. Struktury te można również wykorzystać do odpowiedzi na żądania pochodzące z formularzy.
2) Warstwa usługi zwróci
ValidationResult
s, niezależnie od tego, czy operacja zakończy się powodzeniem, czy nie. Na przykład:3) Kontroler API konstruuje odpowiedź na podstawie wyniku funkcji usługi
Jedną z opcji jest ustawienie praktycznie wszystkich parametrów jako opcjonalnych i przeprowadzenie niestandardowej weryfikacji, która zwraca bardziej znaczącą odpowiedź. Staram się również, aby żaden wyjątek nie wykraczał poza zakres usługi.
źródło
Użyj wbudowanej metody „InternalServerError” (dostępnej w ApiController):
źródło
Wystarczy zaktualizować bieżący stan interfejsu WebAPI programu ASP.NET. Interfejs jest teraz wywoływany,
IActionResult
a implementacja niewiele się zmieniła:źródło
W przypadku błędów, w których modelstate.isvalid ma wartość false, generalnie wysyłam błąd, ponieważ jest generowany przez kod. Łatwo to zrozumieć dla programisty korzystającego z mojej usługi. Generalnie wysyłam wynik za pomocą poniższego kodu.
To wysyła błąd do klienta w poniższym formacie, który jest w zasadzie listą błędów:
źródło