CloudBuilder/CloudBuilder.Core/Request/ServiceRequest.cs
owenchen 2e990e687f ow
2026-05-28 15:05:46 +08:00

460 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CloudBuilder.Core.DependencyInjection.Request;
using CloudBuilder.Core.Policy;
using CloudBuilder.Core.Service;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
/*
注意是否是全局作用域winform如果没有加入局部作用域则都是全局作用域
全局作用域:
using (var scope1 = ServiceProvider.CreateScope())
{
YesNoPolicyRequest yesNoPolicyRequest = ServiceProvider.GetRequiredKeyedService<YesNoPolicyRequest>(typeof(YesNoPolicyRequest).Name);
SelectOption[] selectOptions = yesNoPolicyRequest.FindSelectOption(true);
}
*/
namespace CloudBuilder.Core.Request
{
public class ServiceRequest : IServiceRequest
{
private readonly HttpClient request;
private readonly IConfiguration configuration;
private readonly IServiceProvider provider;
private readonly IContext loginContext;
private JsonSerializerSettings _jsonSettings;
public ServiceRequest(HttpClient request, IConfiguration configuration, IServiceProvider provider)
{
this.request = request;
this.configuration = configuration;
this.provider = provider;
this.loginContext = provider.GetService<IContext>()!;
this.request.BaseAddress = new Uri(this.configuration.GetValue<string>("CloudBuilder:ServiceRequest:BaseAddress")!);
this.request.DefaultRequestHeaders.Add("Accept", this.configuration.GetValue<string>("CloudBuilder:ServiceRequest:DefaultRequestHeaders:Accept"));
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (this.request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
this.request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
this.request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
_jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new DefaultContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateFormatString = "yyyy-MM-dd HH:mm:ss"
};
}
public void SetToken(string token)
{
loginContext.SetToken(token);
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
public void SetCulture(string culture)
{
loginContext.SetCulture(culture);
if (this.request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
this.request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
this.request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, culture);
}
public void SetToken()
{
//如果后面工程注入IContext服務对象那么就会取出GetToken(),如果为空,防止后面工程沒有注入會出錯。
IContext loginContext = provider.GetService<IContext>()!;
if (loginContext != null)
{
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
}
}
public async Task<R> GetAsync<R>(string api)
{
return await GetWithHeadersAndQueryAsync<R>(api, null!, null!);
}
public async Task<R> GetWithQueryAsync<R>(string api, Dictionary<string, string> queryParams)
{
return await GetWithHeadersAndQueryAsync<R>(api, null!, queryParams);
}
public async Task<R> GetWithHeadersAsync<R>(string api, Dictionary<string, string> headers)
{
return await GetWithHeadersAndQueryAsync<R>(api, headers, null!);
}
public async Task<R> GetWithHeadersAndQueryAsync<R>(string api, Dictionary<string, string> headers, Dictionary<string, string> queryParams)
{
string url = api;
if (queryParams != null && queryParams.Count > 0)
{
List<string> query = new List<string>();
foreach (var param in queryParams)
{
query.Add(string.Format("{0}={1}", param.Key, param.Value));
}
url = api + "?" + QuotedString.ToDelimiteredList(query.ToArray(), '&');
}
if (headers != null && headers.Count > 0)
{
foreach (var header in headers)
{
if (request.DefaultRequestHeaders.Contains(header.Key)) request.DefaultRequestHeaders.Remove(header.Key);
request.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var response = await request.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
/*
await request.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)
如果在此处加入ConfigureAwait(false),返回是数组就会出错。
要将ConfigureAwait(false)这个方法放入到下面语句
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
*/
if (!response.IsSuccessStatusCode)
{
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CheckException(responseJson);
return JsonConvert.DeserializeObject<R>(responseJson, _jsonSettings)!;
}
public async Task<R> PostAsJsonAsync<T, R>(string api, T data)
{
return await PostAsJsonAsync<T, R>(api, null!, data);
}
public async Task<R> PostAsJsonAsync<T, R>(string api, Dictionary<string, string> headers, T data)
{
if (headers != null && headers.Count > 0)
{
foreach (var header in headers)
{
if (request.DefaultRequestHeaders.Contains(header.Key)) request.DefaultRequestHeaders.Remove(header.Key);
request.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var options = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var response = await this.request.PostAsJsonAsync(api, data, options);
if (!response.IsSuccessStatusCode)
{
//{"errors":{},"type":"https://tools.ietf.org/html/rfc9110#section-15.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"00-64ad066978f4471cb3c9ce219c213da9-bccca8afd14676b3-00"}
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CheckException(responseJson);
return JsonConvert.DeserializeObject<R>(responseJson, _jsonSettings)!;
}
private void CheckException(string responseJson)
{
if (string.IsNullOrEmpty(responseJson) || !responseJson.StartsWith("{\"SourceCode\":\"CloudBuilder.Core.")) return;
if (responseJson.StartsWith("{\"SourceCode\":\"CloudBuilder.Core.ValidatedException"))
{
ValidatedException vex = JsonConvert.DeserializeObject<ValidatedException>(responseJson, _jsonSettings)!;
throw vex;
}
else if (responseJson.StartsWith("{\"SourceCode\":\"CloudBuilder.Core.ServiceErrorException"))
{
ServiceErrorException sex = JsonConvert.DeserializeObject<ServiceErrorException>(responseJson, _jsonSettings)!;
throw sex;
}
}
public async Task<R> PostAsJsonAsync<R>(string api, Dictionary<string, string> headers)
{
if (headers != null && headers.Count > 0)
{
foreach (var header in headers)
{
if (request.DefaultRequestHeaders.Contains(header.Key)) request.DefaultRequestHeaders.Remove(header.Key);
request.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var response = await this.request.PostAsync(api, null!);
if (!response.IsSuccessStatusCode)
{
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CheckException(responseJson);
return JsonConvert.DeserializeObject<R>(responseJson, _jsonSettings)!;
}
public async Task<R> PostAsJsonAsync<R>(string api)
{
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var response = await this.request.PostAsync(api, new StringContent(string.Empty));
if (!response.IsSuccessStatusCode)
{
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CheckException(responseJson);
return JsonConvert.DeserializeObject<R>(responseJson, _jsonSettings)!;
}
public async Task PostAsync(string api)
{
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var response = await this.request.PostAsync(api, new StringContent(string.Empty));
if (!response.IsSuccessStatusCode)
{
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CheckException(responseJson);
}
public async void DownloadFile(string api, string filePath, Action<long> progressCallback = null!, Action<string> completedCallback = null!)
{
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var response = await this.request.PostAsync(api, new StringContent(string.Empty));
if (!response.IsSuccessStatusCode)
{
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
long? totalBytes = response.Content.Headers.ContentLength;
using (Stream contentStream = await response.Content.ReadAsStreamAsync(),
fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
byte[] buffer = new byte[8192];// 8KB緩衝區
long totalRead = 0;
int read;
while ((read = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, read);
totalRead += read;
if (progressCallback != null) progressCallback(totalRead);
}
}
if (completedCallback != null) completedCallback(filePath);
}
public async Task<Stream> PostStreamAsync<T>(string api, Dictionary<string, string> headers, T data)
{
if (headers != null && headers.Count > 0)
{
foreach (var header in headers)
{
if (request.DefaultRequestHeaders.Contains(header.Key)) request.DefaultRequestHeaders.Remove(header.Key);
request.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var options = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
try
{
var response = await this.request.PostAsJsonAsync(api, data, options).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
//{"errors":{},"type":"https://tools.ietf.org/html/rfc9110#section-15.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"00-64ad066978f4471cb3c9ce219c213da9-bccca8afd14676b3-00"}
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStreamAsync();
}
catch (Exception ex )
{
throw ex;
}
}
public async Task<R> PostAsync<R>(string api, MultipartFormDataContent data)
{
this.request.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", loginContext.GetToken());
if (request.DefaultRequestHeaders.Contains(ClaimPolicy.HEADER_LOCALE))
request.DefaultRequestHeaders.Remove(ClaimPolicy.HEADER_LOCALE);
request.DefaultRequestHeaders.Add(ClaimPolicy.HEADER_LOCALE, loginContext.GetCulture());
var response = await this.request.PostAsync(api, data);
if (!response.IsSuccessStatusCode)
{
var responseContext = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
string errors = string.Empty;
if (responseContext != null && responseContext.StartsWith("{\"errors\"")) errors = responseContext.Substring(11, responseContext.IndexOf("}") - 11);
if (response.ReasonPhrase == "Forbidden")
throw new Exception(string.Format("{0}", CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.NO_PERMISSION)));
throw new Exception(string.Format("{0}{1}", response.ReasonPhrase, string.IsNullOrEmpty(errors) ? "" : "\r\n" + errors));
}
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CheckException(responseJson);
return JsonConvert.DeserializeObject<R>(responseJson, _jsonSettings)!;
}
public void AddHeaders(string name, string? value)
{
request.DefaultRequestHeaders.Add(name, value);
}
public void SetContext(IContext loginContext)
{
this.loginContext.SetCulture(loginContext.GetCulture());
this.loginContext.SetToken(loginContext.GetToken());
}
public HttpClient GetHttpClient() { return request; }
}
}