使用委托包装异常处理时,Web-API 调用不起作用
Posted
技术标签:
【中文标题】使用委托包装异常处理时,Web-API 调用不起作用【英文标题】:Web-API call not working when using delegate to wrap exception handling 【发布时间】:2019-09-28 03:34:45 【问题描述】:我有一个带有自托管 OWIN 的 .NET 4.5.2 应用程序来支持内部 Web api。为了进行一般的异常处理,我尝试将所有调用包装在一个方法“TryOk”中,并以委托作为参数。 TryOk 然后会关心异常并处理它们。
我尝试在没有委托的情况下调用 web-api 并且它有效。只有在使用委托时我才会收到错误。
我将代码减少到最大,并像异步一样删除了所有代码镇流器。
[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);
我收到异常“从 'Microsoft.Owin.Host.HttpListener.RequestProcessing.HttpListenerStreamWrapper' 上的 'Length' 获取值时出错。”内部异常“此流不支持查找操作”。
异常详情:
"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】:您是creating a response over a response,这就是导致您出现该错误的原因。
在这一行,您在回调函数中返回了一个 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:
您甚至可以通过检查您的 callbac func 的返回值来使您的 TryOk
方法更加智能。
try
var returnValue = call();
if(returnValue is IHttpActionResult)
return returnValue;
return Ok(returnValue);
catch(Exception ex)
return BadRequest(ex.Message);
我的另一个建议,我建议你使用全局Exception Filter。
【讨论】:
天哪,我犯了多么愚蠢的错误!我应该自己发现的。感谢您的快速答复。感谢您对前过滤器的推荐。 -jaz @jaz 错误总会发生,所以不要担心。以上是关于使用委托包装异常处理时,Web-API 调用不起作用的主要内容,如果未能解决你的问题,请参考以下文章