2017-06-29 9 views
0

APIサイト(WebApi)を使用するXコントローラがあります。私はApiHelperクラスを作成しました。私はこれらのコントローラで使用します。今私の質問はこれです。このApiHelperを静的クラスにすることはできますか?私は、httpClientがインスタンス化されているため、できると思います。または、私は何かを見落としていますか?インスタンス化されたApiHelperである必要がありますか? (静的な使用は時折私を混乱させる)。以下のコード例。UIからのWebApi呼び出しにスタティックヘルパークラスを使用できますか?

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

はい、できます、そして実際にあなたの代わりに、それぞれの用途にそれを配置するのHttpClientインスタンスを再使用する必要があります。私はこれがIDisposableについて知っているすべてに反していることを知っていますが、[HttpClientは特別です。](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/) – Crowcoder

+0

あなたのアプローチには技術的に問題はありませんが、それは正常に動作します。しかし、単体テストについて気にしているのであれば、いくつかの困難に遭遇します。 – Dan

+0

Crowcoderと、非常に興味深いHttpClientの投稿に感謝します。いくつかの改善に取り組んでいます。 – ivw

答えて

0

法の適用範囲にHttpClient滞在などの静的クラスを残すため、あなたの静的メソッドを呼び出すたびに異なるHttpClientを使用する何の問題もないでしょう。すべての呼び出し元が共有する静的メンバー(フィールドまたはプロパティ)を使用し、アクセスを同期する必要がある場合(マルチスレッド使用の場合)は安全ではありません。

1

ベースコントローラを作成し、httpクライアントを保護されたものとして非表示にします。

public abstract class BaseController : Controller { protected ApiHelper Api { get; set; } }

は、次に注意public class HomeController : BaseController {}

BaseController

public class ConfigController : BaseController {}

からあなたのコントローラを導き出す:彼らはあなたのヒープが散らばっ作る原因静的クラスを使用しないようにしてください。それらは "高周波"ヒープに割り当てられます。これは決してガベージコレクションされません。

+0

Oleksiiありがとう私は現在BaseControllerを使用しています。 – ivw

0

httpClient your are doing it wrong,singleton pattern)を読み取り、続いてテストした後。私は次のコードを使用して終了しました。主な目標は、1つのhttpClientアプリケーション全体であり、ソケットの枯渇を回避することです。

私がhttpClientを必要とする私のコントローラでは、私はHttpClientSingleton.Instanceを使用します。

ここでは、あなたのAPIを使用するコントローラで継承できるBaseControllerがあります。

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); 
    } 

}

関連する問題