簡體   English   中英

使用相同的 HttpClient 從 MVC 控制器調用 Web API

[英]Call Web API from MVC Controller using the same HttpClient

我有一個 MVC5 項目,我需要從 MVC 控制器調用 Web API 方法。 Web API 使用基於令牌的身份驗證,因此我必須為每次調用傳遞令牌。 我使用下面的代碼在 HTTP 標頭中傳遞令牌:

HttpClient httpClient = new HttpClient();
string baseUrl = "http://localhost:60477/";
dynamic token = Session["token"];
if (token.AccessToken != null)
{
    httpClient.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", token.AccessToken));
}

我的控制器中有多個操作方法,我想使用單個HttpClient和標頭,添加在一個地方,而不是在每個操作方法中添加一個標頭。

我可以將HttpClient標頭注冊代碼放置在 MVC 應用程序中的什么位置,以便它可以對所有控制器通用? 這意味着我不想重復代碼,比如在每個操作方法中添加令牌。 我該怎么做?

Public ActionResult Postuser(UserModel user)
{
    // post code
}

Public ActionResult getuser(UserModel user)
{
    HttpResponseMessage response = httpClient.GetAsync(baseUrl + "api/Admin/GetStates").Result;
    if (response.IsSuccessStatusCode)
    {
        string stateInfo = response.Content.ReadAsStringAsync().Result;
    }

}

Public ActionResult PostRoles(RoleModel role)
{
    // post roles code
}

您可以嘗試創建一個小的幫助程序類來創建您的httpclient對象。 類似的東西

public class HttpClientHelper
{
    public static HttpClient GetHttpClient()
    {
        var MyHttpClient = new HttpClient();
        dynamic _token = HttpContext.Current.Session["token"];
        if (_token == null) throw new ArgumentNullException(nameof(_token));
        MyHttpClient.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", _token.AccessToken));
        return MyHttpClient;
    }
}

然后在你的控制器中調用它作為

public ActionResult getuser(UserModel user)
{
    var httpClient = HttpClientHelper.GetHttpClient();
    HttpResponseMessage response = httpClient.GetAsync(baseUrl + "api/Admin/GetStates").Result;
    if (response.IsSuccessStatusCode)
    {
        string stateInfo = response.Content.ReadAsStringAsync().Result;
    }
}

最好遵循單一職責原則並在它自己的類中提取與另一個服務的交互,例如

public class ServiceClient : IServiceClient
{
    private HttpClient m_Client;        

    public ServiceClient
    {
         m_Client = new HttpClient();
         // Initialize the client as you need here
    }

    public void CallSomeMethod()
    {
        // Call method on the client
    }
}

然后在控制器中注入 IServiceClient 並調用它的方法。 如果您不使用注入(我建議您這樣做),您可以在控制器的構造函數中創建一個新實例。

您可以嘗試在控制器中使用動作過濾器。 嘗試添加一個看起來像這樣的覆蓋 -

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
  // some condition code to target a specific method in the controller
  // Example
  if (filterContext.ActionDescriptor.ActionName == "getuser") // <-- your method
  {
    // put your token based authentication code here
  }

  base.OnActionExecuting(filterContext);
}

OnActionExecuting 方法位於控制器范圍內,因此您可以為不同的控制器設置不同的邏輯。

如果您想在操作方法之后運行代碼,還有一個 OnActionExecuted 方法覆蓋。

------編輯--------------

至於放置 HttpClient 代碼片段的位置,您可以試試這個-

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
  HttpClient httpClient = new HttpClient();
  string baseUrl = "http://localhost:60477/";
  dynamic token = Session["token"];

  if (token.AccessToken != null)
  {
    httpClient.DefaultRequestHeaders.Add(
        "Authorization",
        string.Format("Bearer {0}", token.AccessToken)
    );

    httpClient.BaseAddress = new Uri(baseUrl);
  }

  if(filterContext.ActionParameters.ContainsKey("httpClient"))
  {
    filterContext.ActionParameters["httpClient"] = httpClient;
  }
  else
  {
    // error
  }

  base.OnActionExecuting(filterContext);
}

因此 HttpClient 對象以及您的 baseUrl 的分配是在 OnActionExecuting 中建立的。 此代碼將在您正在重構的控制器中返回 ActionResult 的任何方法之前運行。 如果您想針對某些方法而不是所有方法,請參閱上面 OnActionExecuting 的第一個示例。

public ActionResult getuser(UserModel user, HttpClient httpClient)
{
  HttpResponseMessage response = httpClient.GetAsync("api/Admin/GetStates").Result;

  if(response.IsSuccessStatusCode)
  {
    string stateInfo = response.Content.ReadAsStringAsync().Result;
  }

  // the rest of your code for getuser..

  return View();
}

現在您的 getuser 方法有一個額外的參數( HttpClient httpClient )。

為什么不在 Global asax 中移動代碼或創建自定義 Atribute?

這是一個很好的鏈接: http : //www.diaryofaninja.com/blog/2011/07/24/writing-your-own-custom-aspnet-mvc-authorize-attributes

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM