2015-03-03 16 views
9

Sto utilizzando WebAPI v2.2 e sto ottenendo WebAPI per deserializzare JSON su un oggetto utilizzando l'attributo [FromBody]. La classe di destinazione del deserialisation ha un attributo [OnDeserialized] su un metodo interno, in questo modo:Cattura l'eccezione durante la deserializzazione della richiesta in WebAPI C#

[OnDeserialized] 
internal void OnDeserialisedMethod(StreamingContext context) { 
    // my method code 
} 

io so per certo che c'è un problema con il codice all'interno di questo metodo, ho fatto un passo attraverso di essa e trovato. Il problema per me è che non ho alcuna eccezione. Quello che succede è che questo metodo viene saltato fuori e l'eccezione sembra essere ignorata. Viene richiamata l'azione del mio controller e il mio oggetto target non è popolato correttamente perché questo metodo di serializzazione non è stato eseguito correttamente.

La mia domanda è; come posso catturare un'eccezione che si verifica durante la deserializzazione in WebAPI?

+0

http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling –

+0

Ho fatto come suggerito su quella pagina web ma ancora non seleziona l'eccezione? Derivando dalla classe ExceptionHandler e registrando con 'config.Services.Replace (typeof (IExceptionHandler), new Exceptions.MyExceptionHandler());' – Anupheaus

+0

In realtà ottengono l'eccezione, ma non l'eccezione che desidero. Rileva l'eccezione in cui la mia classe di destinazione non è popolata correttamente, non vede ancora alcuna eccezione dal metodo OnDeserialized. Devo rilevare gli errori PRIMA che entri nel metodo di azione del controller e questo sembra essere un problema qui, sembrano essere semplicemente ignorati. – Anupheaus

risposta

9

ho scritto un filtro (come suggerito in vari commenti) che controlla ModelState e genera un'eccezione se si verificano errori di serializzazione. Fate attenzione, tuttavia, che questo non può contenere solo eccezioni di serializzazione, che potrebbero essere regolate specificando il tipo di eccezione concreta nell'istruzione Select.

public class ValidModelsOnlyFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if (actionContext.ModelState.IsValid) 
     { 
      base.OnActionExecuting(actionContext); 
     } 
     else 
     { 
      var exceptions = new List<Exception>(); 

      foreach (var state in actionContext.ModelState) 
      { 
       if (state.Value.Errors.Count != 0) 
       { 
        exceptions.AddRange(state.Value.Errors.Select(error => error.Exception)); 
       } 
      } 

      if (exceptions.Count > 0) 
       throw new AggregateException(exceptions); 
     } 
    } 
} 

Suggerisco di legare questo filtro su un ambito globale. Non riesco davvero a capire perché dovrebbe essere ok ignorare le eccezioni di deserializzazione.

1

È possibile controllare ModelState.IsValid all'interno del controller. Se "OnDeserialisedMethod" lancia un'eccezione (o qualsiasi altra convalida del modello fallisce) sarà false, se tutto avrà successo sarà vero.

2

Ho avuto esattamente lo stesso problema e ho inserito la domanda nella speranza che qualcuno possa fornire una soluzione. Ho pensato che l'uso di ModelState implicasse la riscrittura di alcune convalide nel modello JSON, ma funziona, infatti è semplice e molto ben fatto. Non ho dovuto modificare il modello, solo i controller.

Il mio codice da uno dei miei controllori, StdResponse essendo la classe utilizzata per fornire la risposta con i dettagli, se necessario (in questo caso, per esempio):

[HttpPost] 
public StdResponse Test([FromBody]StdRequest request) 
{ 
    if (ModelState.IsValid) 
    { 
     //Work on the data from the request... 
    } 
    else 
    { 
     //Retrieve the exceptions raised during deserialization 
     var errors = ModelState.SelectMany(v => v.Value.Errors.Select(e => e.Exception)); 

     List<String> messages = new List<string>(); 

     foreach (Exception e in errors) 
     { 
      messages.Add(e.GetType().ToString() + ": " + e.Message); 
     } 

     return new StdResponse(exchangeVersion, "null", ExecutionResponse.WithError("StdRequest invalid", messages)); 
    } 
} 
Problemi correlati