Rzuć HttpResponseException lub żądanie zwrotu.Createerroresponse?

Po przejrzeniu artykułu Obsługa wyjątków w ASP.NET Web API jestem trochę zdezorientowany, kiedy rzucić wyjątek i zwrócić odpowiedź na błąd. Zastanawiam się również, czy jest możliwe zmodyfikowanie odpowiedzi, gdy twoja metoda zwraca model specyficzny dla domeny zamiast HttpResponseMessage...

Podsumowując, oto moje pytania, po których następuje kod z case #s:

Pytania

Pytania dotyczące sprawy # 1

  1. Czy Powinienem Zawsze używaj HttpResponseMessage zamiast konkretnego modelu domeny, aby wiadomość mogła zostać dostosowana?
  2. czy można dostosować wiadomość, jeśli zwracasz konkretny model domeny?

Pytania dotyczące sprawy # 2,3,4

  1. Czy powinienem rzucać wyjątek lub zwracać odpowiedź na błąd? Jeśli odpowiedź brzmi "to zależy", czy możesz podać sytuacje / przykłady, kiedy użyć jednego vs drugiego.
  2. Jaka jest różnica między rzucaniem HttpResponseException a Request.CreateErrorResponse? Wyjście do klient wydaje się identyczny...
  3. Czy zawsze powinienem używać HttpError do "zawijania" wiadomości odpowiedzi w Błędy (niezależnie od tego, czy wyjątek zostanie wyrzucony, czy zwrócona odpowiedź błędu)?

Case Samples

// CASE #1
public Customer Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var notFoundResponse = new HttpResponseMessage(HttpStatusCode.NotFound);
        throw new HttpResponseException(notFoundResponse);
    }
    //var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    //response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return customer;
}        

// CASE #2
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var notFoundResponse = new HttpResponseMessage(HttpStatusCode.NotFound);
        throw new HttpResponseException(notFoundResponse);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

// CASE #3
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var message = String.Format("customer with id: {0} was not found", id);
        var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
        throw new HttpResponseException(errorResponse);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

// CASE #4
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var message = String.Format("customer with id: {0} was not found", id);
        var httpError = new HttpError(message);
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

Update

Aby pomóc w dalszym zademonstrowaniu przypadków #2,3,4 poniższy fragment kodu podkreśla kilka opcji, które "mogą się zdarzyć", gdy klient nie zostanie znaleziony...

if (customer == null)
{
    // which of these 4 options is the best strategy for Web API?

    // option 1 (throw)
    var notFoundMessage = new HttpResponseMessage(HttpStatusCode.NotFound);
    throw new HttpResponseException(notFoundMessage);

    // option 2 (throw w/ HttpError)
    var message = String.Format("Customer with id: {0} was not found", id);
    var httpError = new HttpError(message);
    var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
    throw new HttpResponseException(errorResponse);

    // option 3 (return)
    var message = String.Format("Customer with id: {0} was not found", id);
    return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
    // option 4 (return w/ HttpError)
    var message = String.Format("Customer with id: {0} was not found", id);
    var httpError = new HttpError(message);
    return Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
}
Author: abatishchev, 2012-09-20

9 answers

Moje podejście polega na wyrzuceniu WYJĄTKÓW z akcji kontrolera api i zarejestrowaniu filtra WYJĄTKÓW, który przetwarza wyjątek i ustawia odpowiednią odpowiedź na kontekst wykonywania akcji.

Filtr wyświetla płynny interfejs, który zapewnia sposób rejestrowania procedur obsługi dla określonych typów wyjątków przed zarejestrowaniem filtra z konfiguracją globalną.

Użycie tego filtra umożliwia scentralizowaną obsługę wyjątków zamiast rozprzestrzenianie go po akcjach kontrolera. Są jednak przypadki, w których wyłapię wyjątki w akcji kontrolera i zwrócę konkretną odpowiedź, jeśli centralizacja obsługi tego wyjątku nie ma sensu.

Przykładowa Rejestracja filtra:

GlobalConfiguration.Configuration.Filters.Add(
    new UnhandledExceptionFilterAttribute()
    .Register<KeyNotFoundException>(HttpStatusCode.NotFound)

    .Register<SecurityException>(HttpStatusCode.Forbidden)

    .Register<SqlException>(
        (exception, request) =>
        {
            var sqlException = exception as SqlException;

            if (sqlException.Number > 50000)
            {
                var response            = request.CreateResponse(HttpStatusCode.BadRequest);
                response.ReasonPhrase   = sqlException.Message.Replace(Environment.NewLine, String.Empty);

                return response;
            }
            else
            {
                return request.CreateResponse(HttpStatusCode.InternalServerError);
            }
        }
    )
);

UnhandledExceptionFilterAttribute class:

using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http.Filters;

namespace Sample
{
    /// <summary>
    /// Represents the an attribute that provides a filter for unhandled exceptions.
    /// </summary>
    public class UnhandledExceptionFilterAttribute : ExceptionFilterAttribute
    {
        #region UnhandledExceptionFilterAttribute()
        /// <summary>
        /// Initializes a new instance of the <see cref="UnhandledExceptionFilterAttribute"/> class.
        /// </summary>
        public UnhandledExceptionFilterAttribute() : base()
        {

        }
        #endregion

        #region DefaultHandler
        /// <summary>
        /// Gets a delegate method that returns an <see cref="HttpResponseMessage"/> 
        /// that describes the supplied exception.
        /// </summary>
        /// <value>
        /// A <see cref="Func{Exception, HttpRequestMessage, HttpResponseMessage}"/> delegate method that returns 
        /// an <see cref="HttpResponseMessage"/> that describes the supplied exception.
        /// </value>
        private static Func<Exception, HttpRequestMessage, HttpResponseMessage> DefaultHandler = (exception, request) =>
        {
            if(exception == null)
            {
                return null;
            }

            var response            = request.CreateResponse<string>(
                HttpStatusCode.InternalServerError, GetContentOf(exception)
            );
            response.ReasonPhrase   = exception.Message.Replace(Environment.NewLine, String.Empty);

            return response;
        };
        #endregion

        #region GetContentOf
        /// <summary>
        /// Gets a delegate method that extracts information from the specified exception.
        /// </summary>
        /// <value>
        /// A <see cref="Func{Exception, String}"/> delegate method that extracts information 
        /// from the specified exception.
        /// </value>
        private static Func<Exception, string> GetContentOf = (exception) =>
        {
            if (exception == null)
            {
                return String.Empty;
            }

            var result  = new StringBuilder();

            result.AppendLine(exception.Message);
            result.AppendLine();

            Exception innerException = exception.InnerException;
            while (innerException != null)
            {
                result.AppendLine(innerException.Message);
                result.AppendLine();
                innerException = innerException.InnerException;
            }

            #if DEBUG
            result.AppendLine(exception.StackTrace);
            #endif

            return result.ToString();
        };
        #endregion

        #region Handlers
        /// <summary>
        /// Gets the exception handlers registered with this filter.
        /// </summary>
        /// <value>
        /// A <see cref="ConcurrentDictionary{Type, Tuple}"/> collection that contains 
        /// the exception handlers registered with this filter.
        /// </value>
        protected ConcurrentDictionary<Type, Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>> Handlers
        {
            get
            {
                return _filterHandlers;
            }
        }
        private readonly ConcurrentDictionary<Type, Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>> _filterHandlers = new ConcurrentDictionary<Type, Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>>();
        #endregion

        #region OnException(HttpActionExecutedContext actionExecutedContext)
        /// <summary>
        /// Raises the exception event.
        /// </summary>
        /// <param name="actionExecutedContext">The context for the action.</param>
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            if(actionExecutedContext == null || actionExecutedContext.Exception == null)
            {
                return;
            }

            var type    = actionExecutedContext.Exception.GetType();

            Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> registration = null;

            if (this.Handlers.TryGetValue(type, out registration))
            {
                var statusCode  = registration.Item1;
                var handler     = registration.Item2;

                var response    = handler(
                    actionExecutedContext.Exception.GetBaseException(), 
                    actionExecutedContext.Request
                );

                // Use registered status code if available
                if (statusCode.HasValue)
                {
                    response.StatusCode = statusCode.Value;
                }

                actionExecutedContext.Response  = response;
            }
            else
            {
                // If no exception handler registered for the exception type, fallback to default handler
                actionExecutedContext.Response  = DefaultHandler(
                    actionExecutedContext.Exception.GetBaseException(), actionExecutedContext.Request
                );
            }
        }
        #endregion

        #region Register<TException>(HttpStatusCode statusCode)
        /// <summary>
        /// Registers an exception handler that returns the specified status code for exceptions of type <typeparamref name="TException"/>.
        /// </summary>
        /// <typeparam name="TException">The type of exception to register a handler for.</typeparam>
        /// <param name="statusCode">The HTTP status code to return for exceptions of type <typeparamref name="TException"/>.</param>
        /// <returns>
        /// This <see cref="UnhandledExceptionFilterAttribute"/> after the exception handler has been added.
        /// </returns>
        public UnhandledExceptionFilterAttribute Register<TException>(HttpStatusCode statusCode) 
            where TException : Exception
        {

            var type    = typeof(TException);
            var item    = new Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>(
                statusCode, DefaultHandler
            );

            if (!this.Handlers.TryAdd(type, item))
            {
                Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> oldItem = null;

                if (this.Handlers.TryRemove(type, out oldItem))
                {
                    this.Handlers.TryAdd(type, item);
                }
            }

            return this;
        }
        #endregion

        #region Register<TException>(Func<Exception, HttpRequestMessage, HttpResponseMessage> handler)
        /// <summary>
        /// Registers the specified exception <paramref name="handler"/> for exceptions of type <typeparamref name="TException"/>.
        /// </summary>
        /// <typeparam name="TException">The type of exception to register the <paramref name="handler"/> for.</typeparam>
        /// <param name="handler">The exception handler responsible for exceptions of type <typeparamref name="TException"/>.</param>
        /// <returns>
        /// This <see cref="UnhandledExceptionFilterAttribute"/> after the exception <paramref name="handler"/> 
        /// has been added.
        /// </returns>
        /// <exception cref="ArgumentNullException">The <paramref name="handler"/> is <see langword="null"/>.</exception>
        public UnhandledExceptionFilterAttribute Register<TException>(Func<Exception, HttpRequestMessage, HttpResponseMessage> handler) 
            where TException : Exception
        {
            if(handler == null)
            {
              throw new ArgumentNullException("handler");
            }

            var type    = typeof(TException);
            var item    = new Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>>(
                null, handler
            );

            if (!this.Handlers.TryAdd(type, item))
            {
                Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> oldItem = null;

                if (this.Handlers.TryRemove(type, out oldItem))
                {
                    this.Handlers.TryAdd(type, item);
                }
            }

            return this;
        }
        #endregion

        #region Unregister<TException>()
        /// <summary>
        /// Unregisters the exception handler for exceptions of type <typeparamref name="TException"/>.
        /// </summary>
        /// <typeparam name="TException">The type of exception to unregister handlers for.</typeparam>
        /// <returns>
        /// This <see cref="UnhandledExceptionFilterAttribute"/> after the exception handler 
        /// for exceptions of type <typeparamref name="TException"/> has been removed.
        /// </returns>
        public UnhandledExceptionFilterAttribute Unregister<TException>()
            where TException : Exception
        {
            Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> item = null;

            this.Handlers.TryRemove(typeof(TException), out item);

            return this;
        }
        #endregion
    }
}

Kod źródłowy można również znaleźć tutaj .

 105
Author: Oppositional,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-16 13:24:28

Jeśli nie zwracasz HttpResponseMessage , a zamiast tego zwracasz bezpośrednio klasy entity/model, rozwiązaniem, które uznałem za przydatne, jest dodanie następującej funkcji użytkowej do mojego kontrolera

private void ThrowResponseException(HttpStatusCode statusCode, string message)
{
    var errorResponse = Request.CreateErrorResponse(statusCode, message);
    throw new HttpResponseException(errorResponse);
}

I po prostu wywołaj go z odpowiednim kodem stanu i Komunikatem

 25
Author: Joe King,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-05 13:11:53

Nie rzucaj HttpResponseException ani nie zwracaj HttpResponesMessage dla błędów - z wyjątkiem, jeśli intencją jest zakończenie żądania z taki dokładny wynik.

HttpResponseException są nie Obsługiwane tak samo jak inne wyjątki . Są one nie są przechwytywane w filtrach WYJĄTKÓW . Są one nie są przechwytywane w programie obsługi wyjątków . Są sprytnym sposobem na poślizg w HttpResponseMessage podczas kończenia wykonywania bieżącego kodu / align = "left" /

O ile kod nie jest kodem infrastruktury opierającym się na tej specjalnej obsłudze, unikaj używając typu HttpResponseException!

HttpResponseMessage nie są wyjątkami. Nie przerywają one wykonywania bieżącego kodu. Mogą nie być filtrowane jako wyjątki. Mogą nie być rejestrowane jako wyjątki. Reprezentują one poprawny wynik - nawet odpowiedź 500 jest "poprawną odpowiedzią bez wyjątku"!


Uprość życie:

Kiedy istnieje przypadek wyjątkowy/błąd, śmiało i rzuć normalny wyjątek. NET - lub niestandardowy typ wyjątku aplikacji (, a nie wywodzący się z HttpResponseException) z żądanymi właściwościami "http error/response", takimi jak kod stanu - zgodnie z normalna obsługa wyjątków.

Użyj filtrów wyjątków / programów obsługi wyjątków/rejestratorów WYJĄTKÓW, aby zrobić coś odpowiedniego z tymi wyjątkowymi przypadkami: zmienić / dodać kody statusu? dodać identyfikatory śledzenia? zawierać ślady stosu? log?

Unikając HttpResponseException Obsługa 'wyjątkowych przypadków' jest jednolita i może być obsługiwana jako część odsłoniętego potoku! Na przykład można przekształcić "NotFound" w 404 i "ArgumentException" w 400 i "NullReference" w 500 łatwo i jednolicie z wyjątkami na poziomie aplikacji-jednocześnie umożliwiając rozszerzalność w celu zapewnienia "podstaw", takich jak rejestrowanie błędów.

 17
Author: user2864740,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-13 20:27:39

Case #1

  1. niekoniecznie, w potoku są inne miejsca do modyfikowania odpowiedzi (filtry akcji, programy obsługi wiadomości).
  2. patrz powyżej -- ale jeśli akcja zwraca model domeny, to nie można zmodyfikować odpowiedzi wewnątrz akcji.

Przypadki # 2-4

  1. główne powody rzucania HttpResponseException to:
    • Jeśli zwracasz model domeny, ale musisz obsłużyć przypadki błędów,
    • Aby uprościć logikę kontrolera przez traktowanie błędów jako WYJĄTKÓW
  2. Powinny być równoważne; HttpResponseException zawiera HttpResponseMessage, który jest zwracany jako odpowiedź HTTP.

    Np. przypadek #2 może być przepisany jako

    public HttpResponseMessage Get(string id)
    {
        HttpResponseMessage response;
        var customer = _customerService.GetById(id);
        if (customer == null)
        {
            response = new HttpResponseMessage(HttpStatusCode.NotFound);
        }
        else
        {
            response = Request.CreateResponse(HttpStatusCode.OK, customer);
            response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
        }
        return response;
    }
    

    ... ale jeśli logika kontrolera jest bardziej skomplikowana, dodanie wyjątku może uprościć przepływ kodu.

  3. HttpError zapewnia spójny format dla ciała odpowiedzi i może być serializowany do JSON / XML / etc, ale to nie jest wymagane. na przykład, możesz nie chcieć zawierać encji-body w odpowiedzi, lub możesz chcieć innego formatu.

 15
Author: Mike Wasson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-20 22:56:47

Innym przypadkiem, kiedy użyć HttpResponseException zamiast Response.CreateResponse(HttpStatusCode.NotFound), lub innego kodu stanu błędu, jest sytuacja, gdy masz transakcje w filtrach akcji i chcesz, aby transakcje zostały wycofane po zwróceniu klientowi odpowiedzi na błąd.

Użycie Response.CreateResponse nie cofnie transakcji, podczas gdy rzucenie wyjątku spowoduje.

 9
Author: Rob Gray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-03 12:18:14

chcę podkreślić, że z mojego doświadczenia wynika, że jeśli rzucanie HttpResponseException zamiast zwracania HttpResponseMessage w metodzie webapi 2, to jeśli połączenie zostanie wykonane natychmiast do IIS Express, to timeout lub zwróci 200, ale z błędem html w odpowiedzi. Najprostszym sposobem na przetestowanie tego jest zrobienie $.wywołanie ajax do metody, która rzuca HttpResponseException i w errorCallBack w ajax wykonać natychmiastowe wywołanie do innej metody lub nawet prostej strony http. Ty zauważy, że połączenie imediate nie powiedzie się. Jeśli dodasz punkt przerwania lub settimeout () w wywołaniu błędu, aby opóźnić drugie wywołanie o sekundę lub dwie, dając serwerowi czas na odzyskanie działa poprawnie. To sprawia, że nie od, ale jego prawie jak throw HttpResponseException powoduje wyjście wątku słuchacza po stronie serwera i ponowne uruchomienie, powodując ułamek sekundy bez serwera akceptującego połączenia lub coś.

Update: główną przyczyną limitu czasu połączenia wierd Ajax jest to, że wywołanie ajax jest wykonywane wystarczająco szybko, to samo połączenie tcp jest używane. Podnosiłem eter błędu 401, zwracając HttpResonseMessage lub rzucając HTTPResponseException, który został zwrócony do połączenia ajax przeglądarki. Ale wraz z tym wywołaniem MS zwrócił błąd obiektu nie znaleziono, ponieważ podczas uruchamiania.Auth.aplikacja vb.Usercookieeauthentication był włączony, więc próbował zwrócić przechwytywanie odpowiedzi i dodać przekierowanie, ale błąd z Obiekt nie instancja obiektu. Ten błąd był html, ale był dołączony do odpowiedzi po fakcie, więc tylko wtedy, gdy połączenie ajax zostało wykonane wystarczająco szybko i to samo połączenie tcp używane, czy to się wrócił do przeglądarki, a następnie dostał dołączony do przodu następnego połączenia. Z jakiegoś powodu Chrome właśnie timedout, fiddler pucked becasue mix json i htm, ale firefox RT odwrócił prawdziwy błąd. Więc dziwne, ale sniffer pakietów lub firefox był jedynym sposobem, aby wyśledzić ten jeden w dół.

Należy również zauważyć, że jeśli korzystasz z pomocy Web API do Wygeneruj automatyczną pomoc i zwracasz HttpResponseMessage, następnie powinieneś dodać

[System.Web.Http.Description.ResponseType(typeof(CustomReturnedType))] 

Atrybut do metody, więc pomoc generuje poprawnie. Then

return Request.CreateResponse<CustomReturnedType>(objCustomeReturnedType) 

Or on error

return Request.CreateErrorResponse( System.Net.HttpStatusCode.InternalServerError, new Exception("An Error Ocurred"));

Mam nadzieję, że pomoże to komuś innemu, kto może uzyskać losowy limit czasu lub serwer niedostępny natychmiast po rzuceniu HttpResponseException.

Również zwracanie HttpResponseException ma dodatkową zaletę, że nie powoduje złamania Visual Studio na niezabezpieczonym wyjątku gdy błąd jest zwracany jest AuthToken musi być odświeżony w aplikacji pojedynczej strony.

Aktualizacja: wycofuję moje oświadczenie o IIS Express timing out, stało się to błędem w mojej stronie klienta ajax call back okazuje się, że od Ajax 1.8 zwracając $.ajax () i zwracanie $.ajax.().then () obie zwracają obietnicę, ale nie tę samą obietnicę łańcuchową then () zwraca nową obietnicę, która spowodowała, że kolejność wykonania jest błędna. Kiedy więc obietnica then() się wypełniła była limit czasu skryptu. Dziwne, ale nie IIS express problem między klawiaturą a krzesłem.

 3
Author: Andrew DeVries,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-11 18:46:55

Z tego, co wiem, czy rzucasz wyjątek, czy zwracasz prośbę.Createerroresponse, wynik jest taki sam. Jeśli spojrzysz na kod źródłowy systemu.Www.Http.dll, zobaczysz jak wiele. Spójrz na to ogólne podsumowanie i bardzo podobne rozwiązanie, które zrobiłem: Web Api, HttpError i zachowanie WYJĄTKÓW

 0
Author: Andy Cohen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-06 03:39:55

W sytuacjach błędów, chciałem zwrócić konkretną klasę szczegółów błędu, w dowolnym formacie żądanym przez Klienta zamiast obiektu happy path.

Chcę, aby moje metody kontrolera zwróciły obiekt happy path specyficzny dla domeny i wyrzuciły wyjątek w przeciwnym razie.

Problem polegał na tym, że konstruktory HttpResponseException nie zezwalają na obiekty domeny.

To jest to, co w końcu wymyśliłem

public ProviderCollection GetProviders(string providerName)
{
   try
   {
      return _providerPresenter.GetProviders(providerName);
   }
   catch (BadInputValidationException badInputValidationException)
   {
     throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest,
                                          badInputValidationException.Result));
   }
}

Result jest klasą, która zawiera błąd szczegóły, podczas gdy ProviderCollection jest wynikiem mojej szczęśliwej ścieżki.

 0
Author: NickBeaugié,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-10 17:08:07

Lubię odpowiedź opozycyjna

W każdym razie, potrzebowałem sposobu, aby złapać odziedziczony wyjątek i to rozwiązanie nie spełnia wszystkich moich potrzeb.

Więc skończyło się na zmianie jak on obsługuje OnException i to jest moja wersja

public override void OnException(HttpActionExecutedContext actionExecutedContext) {
   if (actionExecutedContext == null || actionExecutedContext.Exception == null) {
      return;
   }

   var type = actionExecutedContext.Exception.GetType();

   Tuple<HttpStatusCode?, Func<Exception, HttpRequestMessage, HttpResponseMessage>> registration = null;

   if (!this.Handlers.TryGetValue(type, out registration)) {
      //tento di vedere se ho registrato qualche eccezione che eredita dal tipo di eccezione sollevata (in ordine di registrazione)
      foreach (var item in this.Handlers.Keys) {
         if (type.IsSubclassOf(item)) {
            registration = this.Handlers[item];
            break;
         }
      }
   }

   //se ho trovato un tipo compatibile, uso la sua gestione
   if (registration != null) {
      var statusCode = registration.Item1;
      var handler = registration.Item2;

      var response = handler(
         actionExecutedContext.Exception.GetBaseException(),
         actionExecutedContext.Request
      );

      // Use registered status code if available
      if (statusCode.HasValue) {
         response.StatusCode = statusCode.Value;
      }

      actionExecutedContext.Response = response;
   }
   else {
      // If no exception handler registered for the exception type, fallback to default handler
      actionExecutedContext.Response = DefaultHandler(actionExecutedContext.Exception.GetBaseException(), actionExecutedContext.Request
      );
   }
}

Rdzeniem jest ta pętla, w której sprawdzam, czy typ wyjątku jest podklasą zarejestrowanego typu.

foreach (var item in this.Handlers.Keys) {
    if (type.IsSubclassOf(item)) {
        registration = this.Handlers[item];
        break;
    }
}

My2cents

 0
Author: Not Important,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 12:16:41