Wil*_*iam 5 c# exception http httpclient http-headers
我有“集合已修改;枚举操作可能无法执行。” 在我的日志中随机填充的异常,它不是一个持久性错误,而是一个非常随机和烦人的错误。
它似乎源自 System.Net.Http?添加标题时,但我不确定导致此错误弹出的确切原因。我到处寻找这个错误,我理解原因的概念,但是我没有做任何可能抛出这个异常的手动循环和编辑列表(除了添加标题)?
我有一个使用 HTTPClient 与外部 API 通信的服务,这在大多数情况下都有效,但有时会因上述异常而失败,我尝试调试它,但似乎找不到解决方案!希望有人能发现问题并以正确的方式指出我。
例外:
Source: System.Private.CoreLib
Message: Collection was modified; enumeration operation may not execute.
Stack trace: at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Net.Http.Headers.HttpHeaders.AddHeaderInfo(HeaderDescriptor descriptor, HeaderStoreItemInfo sourceInfo)
at System.Net.Http.Headers.HttpHeaders.AddHeaders(HttpHeaders sourceHeaders)
at System.Net.Http.Headers.HttpRequestHeaders.AddHeaders(HttpHeaders sourceHeaders)
at System.Net.Http.HttpClient.PrepareRequestMessage(HttpRequestMessage request)
at System.Net.Http.HttpClient.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.PostAsync(String requestUri, HttpContent content)
at Hidden.Core.Service.BlaService.MyMethod(MyMethodModel model) in C:\Source\Hidden.Core\Service\BlaService.cs:line 168
at Hidden.Web.Api.Controllers.ResourceController.MyMethod(MyMethodModel model) in C:\Source\Hidden.Web.Api\Controllers\ResourceController.cs:line 387
at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at System.Threading.Tasks.ValueTask`1.get_Result()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Hidden.Web.Api.Infrastructure.ExceptionHandlerMiddleware.Invoke(HttpContext context, IActionResultExecutor`1 executor) in C:\Source\Hidden.Web.Api\Infrastructure\ExceptionHandlerMiddleware.cs:line 31
Inner Exception:
Run Code Online (Sandbox Code Playgroud)
我的服务:
private static readonly HttpClient client = new HttpClient();
public async Task<HttpResponseMessage> MyMethod(MyMethodModel model)
{
//Escape chars
model.Location = model.Location.Replace("'", "''");
model.DirectoryName = model.DirectoryName.Replace("'", "''");
//Set Endpoint
var sharePointEndpoint = $"https://{model.Hostname}/sites/{model.Site}/_api/web/folders";
//Set default headers
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", model.SharePointToken); //Set token
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
//Pre-Body data setup
ResourceBodyMetaDataModel metaData = new ResourceBodyMetaDataModel() { type = "SP.Folder" };
//Body data setup
var bodyModel = new Dictionary<string, object>();
bodyModel.Add("__metadata", metaData);
bodyModel.Add("ServerRelativeUrl", $"{model.Location}/{model.DirectoryName}/");
//Set content headers
var strContent = new StringContent(JsonConvert.SerializeObject(bodyModel));
strContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
strContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("odata", "verbose"));
// Send request, grab response
var response = await client.PostAsync(sharePointEndpoint, strContent); //Exception Points HERE
//Return response message
return response;
}
Run Code Online (Sandbox Code Playgroud)
概述:
似乎一旦我向我的 API 发送了多个请求,这些请求就会相互冲突,试图覆盖标头。我什至尝试先清除标题然后添加它们,但我仍然遇到了上述问题。该问题还开始包括以下异常:An item with the same key has already been added. Key: System.Net.Http.Headers.HeaderDescriptor
.
解析度:
为了解决这个问题,我重构了我的服务以执行以下操作:
//Setup request
var request = new HttpRequestMessage(HttpMethod.Post, sharePointEndpoint)
{
Content = strContent
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", model.SharePointToken);
request.Headers.Add("Accept", "application/json;odata=verbose");
request.Headers.Add("X-HTTP-Method", "POST");
request.Headers.Add("ContentLength", bodyModelJson.Length.ToString());
// Send request, grab response
var response = await _httpClient.SendAsync(request);
Run Code Online (Sandbox Code Playgroud)
在我的情况下,标题将取决于我想要进行的操作。我删除了为HTTPClient添加默认标头的部分,而是在发出的请求中添加了它们。如您所见,我现在还使用了SendAsync();
我还将HTTPClient作为单例注入。每当我想使用HTTPClient时,我都必须开始使用我的构造函数。
我的服务:
private readonly HttpClient _httpClient;
public MyService(HttpClient httpClient)
{
_httpClient = httpClient;
}
Run Code Online (Sandbox Code Playgroud)
启动.cs:
public void ConfigureServices(IServiceCollection services)
{
/// SERVICES
services.AddSingleton<HttpClient>();
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助其他遇到此问题的人。
归档时间: |
|
查看次数: |
791 次 |
最近记录: |