可以将静态助手类用于WebApi调用(来自UI)吗?

时间:2017-06-29 12:16:02

标签: c# asp.net-web-api

我有使用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;
        }
    }
}

4 个答案:

答案 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 wrongsingleton 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);
            }
        }
    }
}