[英]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.