我想用C#编写一个REST客户端,它可以从配置文件中读取API调用,处理JSON响应,并相应地生成csv文件。还会有另一个配置文件,其中包含每个API调用返回的属性。此客户端应读取此模板配置文件并处理响应。
客户端应该是这样的,它可以与生成JSON响应的所有第三方rest api一起使用。唯一的区别是每个数据源都有不同的配置文件和模板文件。
有没有其他方法来实现上述功能?是否有可用的第三方库可以帮助实现这一点?要实现这一点,什么是一个好的设计方法?
任何帮助都将不胜感激
发布于 2019-02-15 16:58:41
是。有一种方法可以实现此功能,但听起来您在这里提出了多个问题。你可能应该把你的问题分成多个部分。
如果您有一个从多个Rest源提取数据的配置文件,则可以使用如下所示的基于HttpClient的简单Rest客户端:
库在这里:https://github.com/MelbourneDeveloper/RestClient.Net
public class RestClient
{
#region Fields
private readonly HttpClient _HttpClient = new HttpClient();
#endregion
#region Public Properties
public Uri BaseUri => _HttpClient.BaseAddress;
public Dictionary<string, string> Headers { get; private set; } = new Dictionary<string, string>();
public AuthenticationHeaderValue Authorization { get; set; }
public Dictionary<HttpStatusCode, Func<byte[], object>> HttpStatusCodeFuncs = new Dictionary<HttpStatusCode, Func<byte[], object>>();
public IZip Zip;
public ISerializationAdapter SerializationAdapter { get; }
#endregion
#region Constructor
public RestClient(ISerializationAdapter serializationAdapter, Uri baseUri)
{
_HttpClient.BaseAddress = baseUri;
_HttpClient.Timeout = new TimeSpan(0, 3, 0);
SerializationAdapter = serializationAdapter;
}
#endregion
#region Private Methods
private async Task<T> Call<T>(string queryString, HttpVerb httpVerb, string contentType, object body = null)
{
_HttpClient.DefaultRequestHeaders.Clear();
if (Authorization != null)
{
_HttpClient.DefaultRequestHeaders.Authorization = Authorization;
}
HttpResponseMessage result = null;
var isPost = httpVerb == HttpVerb.Post;
if (!isPost)
{
_HttpClient.DefaultRequestHeaders.Clear();
foreach (var key in Headers.Keys)
{
_HttpClient.DefaultRequestHeaders.Add(key, Headers[key]);
}
}
string bodyString = null;
StringContent stringContent = null;
byte[] data = null;
switch (httpVerb)
{
case HttpVerb.Post:
if (body is string bodyAsString)
{
bodyString = bodyAsString;
}
else
{
if (body != null)
{
data = await SerializationAdapter.SerializeAsync(body);
bodyString = SerializationAdapter.Encoding.GetString(data);
}
else
{
bodyString = string.Empty;
}
}
stringContent = new StringContent(bodyString, Encoding.UTF8, contentType);
//Don't know why but this has to be set again, otherwise more text is added on to the Content-Type header...
stringContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
stringContent.Headers.ContentLength = bodyString.Length;
foreach (var key in Headers.Keys)
{
stringContent.Headers.Add(key, Headers[key]);
}
result = await _HttpClient.PostAsync(queryString, stringContent);
break;
case HttpVerb.Get:
result = await _HttpClient.GetAsync(queryString);
break;
case HttpVerb.Delete:
result = await _HttpClient.DeleteAsync(queryString);
break;
case HttpVerb.Put:
case HttpVerb.Patch:
data = await SerializationAdapter.SerializeAsync(body);
bodyString = SerializationAdapter.Encoding.GetString(data);
var length = bodyString.Length;
stringContent = new StringContent(bodyString, SerializationAdapter.Encoding, contentType);
if (httpVerb == HttpVerb.Put)
{
result = await _HttpClient.PutAsync(queryString, stringContent);
}
else
{
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, queryString)
{
Content = stringContent
};
result = await _HttpClient.SendAsync(request);
}
break;
}
if (result.IsSuccessStatusCode)
{
var gzipHeader = result.Content.Headers.ContentEncoding.FirstOrDefault(h => !string.IsNullOrEmpty(h) && h.Equals("gzip", StringComparison.InvariantCultureIgnoreCase));
if (gzipHeader != null && Zip != null)
{
var bytes = await result.Content.ReadAsByteArrayAsync();
data = Zip.Unzip(bytes);
}
else
{
data = await result.Content.ReadAsByteArrayAsync();
}
return await SerializationAdapter.DeserializeAsync<T>(data);
}
var errorData = await result.Content.ReadAsByteArrayAsync();
if (HttpStatusCodeFuncs.ContainsKey(result.StatusCode))
{
return (T)HttpStatusCodeFuncs[result.StatusCode].Invoke(errorData);
}
throw new HttpStatusException($"{result.StatusCode}.\r\nBase Uri: {_HttpClient.BaseAddress}. Full Uri: {_HttpClient.BaseAddress + queryString}", result.StatusCode, errorData);
}
#endregion
#region Public Methods
public async Task<T> GetAsync<T>()
{
return await GetAsync<T>(null);
}
public async Task<T> GetAsync<T>(string queryString, string contentType = "application/json")
{
return await Call<T>(queryString, HttpVerb.Get, contentType);
}
public async Task<TReturn> PostAsync<TReturn, TBody>(TBody body, string queryString, string contentType = "application/json")
{
return await Call<TReturn>(queryString, HttpVerb.Post, contentType, body);
}
public async Task<TReturn> PutAsync<TReturn, TBody>(TBody body, string queryString, string contentType = "application/json")
{
return await Call<TReturn>(queryString, HttpVerb.Put, contentType, body);
}
public async Task DeleteAsync(string queryString, string contentType = "application/json")
{
await Call<object>(queryString, HttpVerb.Delete, contentType, null);
}
public async Task<TReturn> PatchAsync<TReturn, TBody>(TBody body, string queryString, string contentType = "application/json")
{
return await Call<TReturn>(queryString, HttpVerb.Patch, contentType, body);
}
#endregion
}用法:
var countryCodeClient = new RestClientDotNet.RestClient(new NewtonsoftSerializationAdapter(), new Uri("http://services.groupkt.com/country/get/all"));
var countryData = await countryCodeClient.GetAsync<groupktResult<CountriesResult>>();https://stackoverflow.com/questions/44361086
复制相似问题