我有使用API站点(WebApi)的X控制器。我创建了一个ApiHelper类。我在这些控制器中使用它。现在我的问题是这个。我可以将这个ApiHelper变成静态类吗?我想我可以,因为httpClient是实例化的。或者我忽略了什么,它是否需要成为实例ApiHelper。 (静态的使用有时会让我困惑)。下面的示例代码。
public class HomeController : Controller
{
public async Task<string> VersionDemo()
{
var response = await ApiHelper.Call("/api/config/version");
var data = response.Content.ReadAsStringAsync();
var res = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(data.Result);
return res;
}
}
public class ConfigController : Controller
{
private async Task<List<ConfigSetting>> GetGeneralConfigurationDemo()
{
var generalConfiguration = new List<ConfigSetting>();
var response = await ApiHelper.Call("api/configuration/GetGeneralConfiguration");
var data = response.Content.ReadAsStringAsync();
generalConfiguration = JsonConvert.DeserializeObject<List<ConfigSetting>>(data.Result);
return generalConfiguration;
}
}
public static class ApiHelper
{
public static async Task<HttpResponseMessage> Call(string url)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var baseAdress = System.Configuration.ConfigurationManager.AppSettings["ApiBaseAddress"];
string apiUrl = baseAdress + url;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(apiUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(apiUrl);
return response;
}
}
}
答案 0 :(得分:1)
制作基本控制器并将http客户端隐藏为受保护的东西。
public abstract class BaseController : Controller
{
protected ApiHelper Api { get; set; }
}
然后从BaseController
派生您的控制器 public class ConfigController : BaseController {}
public class HomeController : BaseController {}
注意:尽量不要使用静态类,因为它们会使您的堆乱丢。它们被分配在“高频”堆中,永远不会被垃圾收集。
答案 1 :(得分:0)
如果HttpClient
停留在方法范围内,那么让您的类保持静态是没有问题的,因此对静态方法的每次调用都将使用不同的HttpClient
。如果您使用静态成员(字段或属性),那将是不安全的,因为它将由所有调用者共享,并且您需要同步访问(对于多线程使用)。
答案 2 :(得分:0)
阅读后(httpClient your are doing it wrong,singleton pattern)并随后进行测试。我最终使用以下代码。主要目标是一个httpClient应用程序范围,避免套接字耗尽。
在我需要httpClient的控制器中,我使用HttpClientSingleton.Instance,见下文。
这是一个BaseController,您可以在将要使用您的API的控制器中继承。
public class BaseController : Controller
{
public readonly string ApiBaseAdress = System.Configuration.ConfigurationManager.AppSettings["ApiBaseAddress"];
public BaseController()
{
//Set as needed Servicepoint settings
//string SecurityProtocolTypeFromConfig = System.Configuration.ConfigurationManager.AppSettings["SecurityProtocolType"];
//SecurityProtocolType fromConfig;
//Enum.TryParse(SecurityProtocolTypeFromConfig, out fromConfig);
//ServicePointManager.SecurityProtocol = fromConfig;
//possible ServicePoint setting needed in some cases.
//ServicePointManager.Expect100Continue = false;
//ServicePointManager.MaxServicePointIdleTime = 2000;
//ServicePointManager.SetTcpKeepAlive(false, 1, 1);
}
}
这是HttpClientSingleton类:
public sealed class HttpClientSingleton
{
private static readonly Lazy<HttpClient> lazy = new Lazy<HttpClient>(() => new HttpClient());
public static HttpClient Instance { get { return lazy.Value; } }
private HttpClientSingleton()
{
}
}
所以把它放在一起。以下是从API获取一些loginfo的示例。
public class MyLogController : BaseController
{
[HttpPost]
public async Task<JsonResult> log(string requestId)
{
var url = ApiBaseAdress + string.Format("/api/runs/log/{0}", requestId);
List<Log> logs = new List<Log>();
var response = await HttpClientSingleton.Instance.GetAsync(url);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
logs = JsonConvert.DeserializeObject<List<Log>>(result);
return Json(logs);
}
}
答案 3 :(得分:0)
您可以编写静态帮助程序类。如果名称为ApiHelper
,则添加一个Microsoft.AspNet.WebApi.Client
引用。初始化应用后,请调用类的InitializeClient()
方法,并且可以根据需要调用GetAsync()
方法。代码如下:
public static class ApiHelper
{
public static HttpClient ApiClient { get; set; }
public static void InitializeClient()
{
ApiClient = new HttpClient();
ApiClient.DefaultRequestHeaders.Accept.Clear();
ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public static async Task<T> GetAsync<T>(string url)
{
using (HttpResponseMessage response = await ApiHelper.ApiClient.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsAsync<T>();
return result;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
}
}