public async Task Execute(CrmRequestMessage request, Func <Task <HttpResponseMessage> > action) { int retryNumber = 0; while (true) { var response = await action(); retryNumber++; if (!response.IsSuccessStatusCode) { //先判断content为空 var requestBody = string.Empty; if (response.RequestMessage.Content != null) { requestBody = await response.RequestMessage.Content.ReadAsStringAsync(); } var strContent = await response.Content.ReadAsStringAsync(); //这个后面没用到,还容易报错,暂时注释 //var error = JsonSerializerHelper.Deserialize<CrmWebApiError>(strContent); UtilityException ex = null; bool canContinue = false; TextFragment fragment; switch ((int)response.StatusCode) { case 412: fragment = new TextFragment() { Code = TextCodes.CrmWebApiConcurrencyError, DefaultFormatting = "调用Crm的webapi出现并发性错误,Uri:{0},Body:{1},错误信息:{2}", ReplaceParameters = new List <object>() { response.RequestMessage.RequestUri.ToString(), requestBody, strContent } }; ex = new UtilityException((int)Errors.CrmWebApiConcurrencyError, fragment); break; case 429: if (retryNumber >= request.MaxRetry) { fragment = new TextFragment() { Code = TextCodes.CrmWebApiLimitError, DefaultFormatting = "调用Crm的webapi出现限制性错误,Uri:{0},Body:{1},错误信息:{2}", ReplaceParameters = new List <object>() { response.RequestMessage.RequestUri.ToString(), requestBody, strContent } }; ex = new UtilityException((int)Errors.CrmWebApiLimitError, fragment); } else { await Task.Delay(response.Headers.RetryAfter.Delta.Value); //System.Threading.Thread.Sleep(response.Headers.RetryAfter.Delta.Value); canContinue = true; } break; default: fragment = new TextFragment() { Code = TextCodes.CrmWebApiCommonError, DefaultFormatting = "调用Crm的webapi出现错误,Uri:{0},Body:{1},错误信息:{2}", ReplaceParameters = new List <object>() { response.RequestMessage.RequestUri.ToString(), requestBody, strContent } }; ex = new UtilityException((int)Errors.CrmWebApiCommonError, fragment); break; } if (ex != null) { throw ex; } if (!canContinue) { break; } } else { break; } } }
public async Task <CrmResponseMessage> Execute(CrmRequestMessage request) { //填充request属性 request.ApiVersion = CrmApiVersion; request.MaxRetry = CrmApiMaxRetry; request.OrganizationURI = CrmUrl; var handle = _crmMessageHandleSelector.Choose(request.GetType().FullName); var requestResult = await handle.ExecuteRequest(request); string strContentType = null; string strContentChartSet = null; Dictionary <string, string> contentParameters = new Dictionary <string, string>(); HttpClient httpClient = null; if (TokenServiceType.ToLower() == CrmServiceTokenGenerateServiceNames.AD.ToLower()) { var userName = TokenServiceParameters[CrmServiceTokenGenerateServiceParameterNames.UserName].ToString(); var password = TokenServiceParameters[CrmServiceTokenGenerateServiceParameterNames.Password].ToString(); var domain = TokenServiceParameters[CrmServiceTokenGenerateServiceParameterNames.Domain].ToString(); httpClient = new HttpClient(new HttpClientHandler() { Credentials = new NetworkCredential(userName, password, domain) }); } else { httpClient = _httpClientFactory.CreateClient(); } using (httpClient) { foreach (var headerItem in requestResult.Headers) { switch (headerItem.Key.ToLower()) { case "content-type": strContentType = await headerItem.Value.ToDisplayString( async (item) => { return(await Task.FromResult(item)); }, async() => { return(await Task.FromResult(";")); } ); break; case "content-type-chartset": strContentChartSet = headerItem.Value.First(); break; case "accept": httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(headerItem.Value.First())); break; default: if (headerItem.Key.ToLower().StartsWith("content-type-")) { contentParameters[headerItem.Key.Substring(13)] = headerItem.Value.First(); break; } httpClient.DefaultRequestHeaders.Add(headerItem.Key, headerItem.Value); break; } } //判断是否需要加入代理 if (request.ProxyUserId != null) { httpClient.DefaultRequestHeaders.Add("MSCRMCallerID", request.ProxyUserId.ToString()); } HttpResponseMessage responseMessage = null; HttpContent httpContent = null; try { await _crmMessageResponseHandle.Execute(request, async() => { //获取令牌 if (TokenServiceType.ToLower() != CrmServiceTokenGenerateServiceNames.AD.ToLower()) { var tokenService = _crmServiceTokenGenerateServiceSelector.Choose(TokenServiceType); var strToken = await tokenService.Genereate(TokenServiceParameters); httpClient.DefaultRequestHeaders.Add("Authorization", strToken); } switch (requestResult.Method.Method.ToLower()) { case "get": responseMessage = await httpClient.GetAsync(requestResult.Url); break; case "post": if (requestResult.ReplaceHttpContent == null) { httpContent = new StringContent(requestResult.Body); if (strContentType != null) { httpContent.Headers.ContentType = new MediaTypeHeaderValue(strContentType); if (strContentChartSet != null) { httpContent.Headers.ContentType.CharSet = strContentChartSet; } foreach (var item in contentParameters) { httpContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue(item.Key, item.Value)); } } } else { httpContent = requestResult.ReplaceHttpContent; } responseMessage = await httpClient.PostAsync(requestResult.Url, httpContent); break; case "put": if (requestResult.ReplaceHttpContent == null) { httpContent = new StringContent(requestResult.Body); if (strContentType != null) { httpContent.Headers.ContentType = new MediaTypeHeaderValue(strContentType); if (strContentChartSet != null) { httpContent.Headers.ContentType.CharSet = strContentChartSet; } foreach (var item in contentParameters) { httpContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue(item.Key, item.Value)); } } } else { httpContent = requestResult.ReplaceHttpContent; } responseMessage = await httpClient.PutAsync(requestResult.Url, httpContent); break; case "patch": if (requestResult.ReplaceHttpContent == null) { httpContent = new StringContent(requestResult.Body); if (strContentType != null) { httpContent.Headers.ContentType = new MediaTypeHeaderValue(strContentType); if (strContentChartSet != null) { httpContent.Headers.ContentType.CharSet = strContentChartSet; } foreach (var item in contentParameters) { httpContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue(item.Key, item.Value)); } } } else { httpContent = requestResult.ReplaceHttpContent; } responseMessage = await httpClient.PatchAsync(requestResult.Url, httpContent); break; case "delete": responseMessage = await httpClient.DeleteAsync(requestResult.Url); break; default: TextFragment fragment = new TextFragment() { Code = TextCodes.CrmMessageExecuteNotSupportMethod, DefaultFormatting = "Crm消息处理不支持名称为{0}的HttpMethod", ReplaceParameters = new List <object>() { requestResult.Method.Method } }; throw new UtilityException((int)Errors.CrmMessageExecuteNotSupportMethod, fragment); } return(responseMessage); }); } finally { if (httpContent != null) { httpContent.Dispose(); } } Dictionary <string, IEnumerable <string> > responseHeaders = new Dictionary <string, IEnumerable <string> >(); foreach (var headerItem in responseMessage.Headers) { responseHeaders.Add(headerItem.Key, headerItem.Value); } var result = await handle.ExecuteResponse(requestResult.Extension, requestResult.Url, requestResult.Body, (int)responseMessage.StatusCode, responseHeaders, await responseMessage.Content.ReadAsStringAsync(), responseMessage); return(result); } }