382 lines
17 KiB
C#
382 lines
17 KiB
C#
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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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<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);
|
||
throw new Exception(string.Format("{0}\r\n{1}", response.ReasonPhrase, 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; }
|
||
}
|
||
}
|