.NET Standard 2、.NET Core 2、HttpClient 未按预期运行(传递 null)
.NET Standard 2, .NET Core 2, HttpClient not behaving as expected (passing null)
小提纲:
我们有一个调用 WebApi (.NET Core 2.0) 的 .NET Standard (2.0) 项目,它应该处理一条消息(通过消息,它可以是用户想要记录的任何内容,可以是异常、警告、或者只是存储在数据库中的注释)存储该消息和 return 更新后的消息给调用者。
问题:
当我从 .NET Standard 项目(使用 HttpClient)调用 WebApi 时,它实际上并没有按要求 POSTing 对象。当它在 .NET Standard 项目中运行时,该对象会填充所有必需的字段,在这种情况下,它会捕获异常并传递消息、堆栈跟踪等。
这是 .NET Standard 项目的代码:
IDataAccessResult<CaughtException> result = new DataAccessResult<CaughtException>();
string baseUrl = "baseurl";
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("a", "b");
// HTTP POST
var myContent = JsonConvert.SerializeObject(caughtException);
StringContent sc = new StringContent(myContent, System.Text.Encoding.UTF8, "application/json");
System.Uri uri = new System.Uri(string.Format("{0}/api/v6/CaughtException/SaveAsync", baseUrl));
HttpResponseMessage response = await client.PostAsync(uri, sc);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
result = JsonConvert.DeserializeObject<DataAccessResult<CaughtException>>(await response.Content.ReadAsStringAsync());
}
当此调用传递给 WebApi 时,该对象不再包含任何数据,而是充满了空值和空字符串,这让我相信 POST 实际上并未发送数据。
在这一点上,我真的不确定我错过了什么。 Google 几乎没有帮助,而且我找不到任何与我的问题类似的东西。
在遍历调用堆栈后,它吐出一些错误消息,同样,我在连接到我的代码时运气不佳,但它们是:
> WinHttpException: The connection with the server was terminated abnormally
> Unknown location
> IOException: The read operation failed, see inner exception.
>System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Threading.Tasks.RendezvousAwaitable.GetResult()
System.Net.Http.WinHttpResponseStream+<CopyToAsyncCore>d__18.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Net.Http.NoWriteNoSeekStreamContent+<>c.<SerializeToStreamAsync>b__4_0(Task t, object s)
System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref Task currentTaskSlot)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Net.Http.HttpContent+<LoadIntoBufferAsyncCore>d__48.MoveNext()
> HttpRequestException: Error while copying content to a stream.
>System.Net.Http.HttpContent+<LoadIntoBufferAsyncCore>d__48.MoveNext()
>System.Net.Http.HttpContent+<LoadIntoBufferAsyncCore>d__48.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Net.Http.HttpClient+<FinishSendAsyncBuffered>d__58.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
LogService.Gateway.CaughtExceptionGateway+<SaveAsync>d__6.MoveNext() in CaughtExceptionGateway.cs
+
HttpResponseMessage response = await client.PostAsync(uri, sc);
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
LogService.Api.CaughtExceptionController+<LogError>d__11.MoveNext() in CaughtExceptionController.cs
+
ce = (await _exceptions.SaveAsync(ce)).Payload;
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
LogService.Api.CaughtExceptionController+<GetCaughtExceptionAsync>d__5.MoveNext() in CaughtExceptionController.cs
+
CaughtException ce = await LogError(action, controller, loggingApplicationCodeId, accountId, loggingExceptionTypeId, e.Exception.Message, e.Exception.StackTrace, null, token, storedProcedureName, storedProcedureParameters);
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__12.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
有人 seen/come across/fixed 这个问题吗?在与 HttpClient 的通话中我做错了什么吗?
好吧,在绝对和彻底的愚蠢行为中(不是一个词,但我需要编造一些东西来解释我现在的感觉有多愚蠢)我想通了这个问题。
webapi 方法签名是罪魁祸首:
public async Task<IActionResult> SaveAsync([FromBody]CaughtException caughtExceptionItem)
我错过了 [FromBody]
。我之前为我们的大多数系统制作了 api,我不知道为什么我错过了这么简单的东西。
希望我的错误(以及随后浪费的时间)能帮助到其他人!!
小提纲:
我们有一个调用 WebApi (.NET Core 2.0) 的 .NET Standard (2.0) 项目,它应该处理一条消息(通过消息,它可以是用户想要记录的任何内容,可以是异常、警告、或者只是存储在数据库中的注释)存储该消息和 return 更新后的消息给调用者。
问题: 当我从 .NET Standard 项目(使用 HttpClient)调用 WebApi 时,它实际上并没有按要求 POSTing 对象。当它在 .NET Standard 项目中运行时,该对象会填充所有必需的字段,在这种情况下,它会捕获异常并传递消息、堆栈跟踪等。
这是 .NET Standard 项目的代码:
IDataAccessResult<CaughtException> result = new DataAccessResult<CaughtException>();
string baseUrl = "baseurl";
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("a", "b");
// HTTP POST
var myContent = JsonConvert.SerializeObject(caughtException);
StringContent sc = new StringContent(myContent, System.Text.Encoding.UTF8, "application/json");
System.Uri uri = new System.Uri(string.Format("{0}/api/v6/CaughtException/SaveAsync", baseUrl));
HttpResponseMessage response = await client.PostAsync(uri, sc);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
result = JsonConvert.DeserializeObject<DataAccessResult<CaughtException>>(await response.Content.ReadAsStringAsync());
}
当此调用传递给 WebApi 时,该对象不再包含任何数据,而是充满了空值和空字符串,这让我相信 POST 实际上并未发送数据。
在这一点上,我真的不确定我错过了什么。 Google 几乎没有帮助,而且我找不到任何与我的问题类似的东西。
在遍历调用堆栈后,它吐出一些错误消息,同样,我在连接到我的代码时运气不佳,但它们是:
> WinHttpException: The connection with the server was terminated abnormally
> Unknown location
> IOException: The read operation failed, see inner exception.
>System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Threading.Tasks.RendezvousAwaitable.GetResult()
System.Net.Http.WinHttpResponseStream+<CopyToAsyncCore>d__18.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Net.Http.NoWriteNoSeekStreamContent+<>c.<SerializeToStreamAsync>b__4_0(Task t, object s)
System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state)
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref Task currentTaskSlot)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Net.Http.HttpContent+<LoadIntoBufferAsyncCore>d__48.MoveNext()
> HttpRequestException: Error while copying content to a stream.
>System.Net.Http.HttpContent+<LoadIntoBufferAsyncCore>d__48.MoveNext()
>System.Net.Http.HttpContent+<LoadIntoBufferAsyncCore>d__48.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Net.Http.HttpClient+<FinishSendAsyncBuffered>d__58.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
LogService.Gateway.CaughtExceptionGateway+<SaveAsync>d__6.MoveNext() in CaughtExceptionGateway.cs
+
HttpResponseMessage response = await client.PostAsync(uri, sc);
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
LogService.Api.CaughtExceptionController+<LogError>d__11.MoveNext() in CaughtExceptionController.cs
+
ce = (await _exceptions.SaveAsync(ce)).Payload;
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
LogService.Api.CaughtExceptionController+<GetCaughtExceptionAsync>d__5.MoveNext() in CaughtExceptionController.cs
+
CaughtException ce = await LogError(action, controller, loggingApplicationCodeId, accountId, loggingExceptionTypeId, e.Exception.Message, e.Exception.StackTrace, null, token, storedProcedureName, storedProcedureParameters);
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__12.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
有人 seen/come across/fixed 这个问题吗?在与 HttpClient 的通话中我做错了什么吗?
好吧,在绝对和彻底的愚蠢行为中(不是一个词,但我需要编造一些东西来解释我现在的感觉有多愚蠢)我想通了这个问题。
webapi 方法签名是罪魁祸首:
public async Task<IActionResult> SaveAsync([FromBody]CaughtException caughtExceptionItem)
我错过了 [FromBody]
。我之前为我们的大多数系统制作了 api,我不知道为什么我错过了这么简单的东西。
希望我的错误(以及随后浪费的时间)能帮助到其他人!!