Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用相同的HttpClient从MVC控制器调用Web API_C#_Asp.net Mvc_Asp.net Web Api_Asp.net Mvc 5 - Fatal编程技术网

C# 使用相同的HttpClient从MVC控制器调用Web API

C# 使用相同的HttpClient从MVC控制器调用Web API,c#,asp.net-mvc,asp.net-web-api,asp.net-mvc-5,C#,Asp.net Mvc,Asp.net Web Api,Asp.net Mvc 5,我有一个MVC5项目,我需要从MVC控制器调用WebAPI方法。Web API使用基于令牌的身份验证,因此我必须为每个调用传递令牌。我使用下面的代码在HTTP头中传递令牌: HttpClient httpClient = new HttpClient(); string baseUrl = "http://localhost:60477/"; dynamic token = Session["token"]; if (token.AccessToken != null) { httpCl

我有一个MVC5项目,我需要从MVC控制器调用WebAPI方法。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
和头,添加在一个位置,而不是在每个操作方法中添加头

在MVC应用程序中,我可以将
HttpClient
headers注册代码放在哪里,这样所有控制器都可以使用它?这意味着我不想重复代码,比如在每个操作方法中添加令牌。我该怎么做

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
}

您可以尝试在控制器中使用操作筛选器。尝试添加类似以下内容的覆盖-

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);
}
因此,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)

为什么不尽快在全局中移动代码或创建自定义Atribute

这里有一个很好的链接:

您可以尝试创建一个小的帮助器类来创建
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;
    }
}

最好坚持单一责任原则,并提取与It自己类中的另一个服务的交互,例如

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注入控制器中,并调用其方法。如果您不使用注入(我建议您这样做),您可以在控制器的构造函数中创建一个新实例。

谢谢。如何在global.asax文件中放置httpclient代码?请参阅我文章的编辑部分。此外,Ilya Chernomordik建议的注入服务和Danny建议的使用助手方法一样理想。我的建议可能不是最好的,但如果你想尝试一下行动过滤器,那就试试吧。添加到方法中的HttpClient参数可以重构为服务对象,以便将OnActionExecuting override方法中的代码注入到服务对象中。希望有帮助!
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
    }
}