Вызов Web-API не работает при использовании делегата для обработки исключений - PullRequest
0 голосов
/ 10 мая 2019

У меня есть приложение .NET 4.5.2 с автономным OWIN для поддержки внутреннего веб-API.Для общей обработки исключений я попытался обернуть все вызовы внутри метода «TryOk» с делегатом в качестве параметра.TryOk затем позаботится об исключениях и обработает их.

Я попытался вызвать web-api без делегата, и это сработало.только при использовании делегата я получаю ошибку.

Я уменьшил код до максимума и удалил весь код balast, например async.

[HttpPost, Route("echo")]
public IHttpActionResult MyEchoApi([FromBody]string echo)
{
    // this is working: direct return
    //return Ok("you say " + echo ?? "nothing");

    // this is also working: direct return with exception handling
    //try { return Ok(call()); }
    //catch (Exception ex) { return BadRequest(ex.Message); }

    // this is not working: wrapping in delegate
    return TryOk(() => { return Ok("you say " + echo ?? "nothing"); });
}

private IHttpActionResult TryOk<T>(Func<T> call)
{
    try { return Ok(call()); }
    catch (Exception ex) { return BadRequest(ex.Message); }
}

Я получаю исключение "Ошибка при получении значения из" Длина'on' Microsoft.Owin.Host.HttpListener.RequestProcessing.HttpListenerStreamWrapper '. "с внутренним исключением "Этот поток не поддерживает операции поиска".

Сведения об исключении:

"ExceptionMessage": "Error getting value from 'Length' on 'Microsoft.Owin.Host.HttpListener.RequestProcessing.HttpListenerStreamWrapper'.",
"ExceptionType": "Newtonsoft.Json.JsonSerializationException",
"StackTrace": "   bei Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   bei Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   bei Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
   bei System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)
   bei System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)
   bei System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
   --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__27.MoveNext()",
"InnerException": {
    "Message": "An error has occurred.",
    "ExceptionMessage": "This stream does not support seek operations.",
    "ExceptionType": "System.NotSupportedException",
    "StackTrace": "   bei System.Net.HttpResponseStream.get_Length()
    bei GetLength(Object )
    bei Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"
}

Что я делаю не так?

Спасибо за любой ответ или идею.

- джаз

1 Ответ

1 голос
/ 10 мая 2019

Вы создаете ответ поверх ответа , и именно поэтому он вызывает эту ошибку.

В этой строке вы вернули IHttpActionResult в функции обратного вызова:

 return TryOk(() => { return Ok("you say " + echo ?? "nothing"); });

вам не нужно звонить Ok(call()), просто позвоните return call().

private IHttpActionResult TryOk<T>(Func<T> call)
{
    // call itself returns an Ok http action result, you are returning a reposnse on another response! just change to call();
    try { return Ok(call()); }
    catch (Exception ex) { return BadRequest(ex.Message); }
}

Редактировать 1:

Вы даже можете сделать свой метод TryOk намного умнее, проверив возвращаемое значение функции callbac.

try
{
    var returnValue = call();

    if(returnValue is IHttpActionResult)
        return returnValue;

    return Ok(returnValue);
}
catch(Exception ex)
{
    return BadRequest(ex.Message);
}

Еще одно предложение, которое я имею, я рекомендую вам использовать глобальный фильтр исключений .

...