Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Web API from MVC Controller using the same HttpClient

I have an MVC5 project, from the MVC controller I need to call the Web API method. The Web API uses token based authentication, so I have to pass the token for each call. I am using the code below to pass the token in the HTTP header:

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

There are multiple action methods in my controller, and I want to use a single HttpClient and headers, added in one place, instead of adding a header in each and every action method.

Where can I place the HttpClient headers registration code in the MVC application, so it can be common to all controllers? That means I don't want to repeat code, like adding the token in each and every action method. How can I do that?

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
}
like image 326
SivaRajini Avatar asked Jan 07 '23 02:01

SivaRajini


2 Answers

You can try creating a small helper class for creating your httpclient object. Something like

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

and then call it in your controllers as

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;
    }
}
like image 65
Dandy Avatar answered Jan 08 '23 14:01

Dandy


It is better to adhere to the Single Responsibility Principle and extract the interaction with another service in a it's own class, e.g.

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

Then you inject the IServiceClient in your controller and just call it's methods. If you do not use injection (which I advise you do) you can just create a new instance in the controller's constructor.

like image 27
Ilya Chernomordik Avatar answered Jan 08 '23 14:01

Ilya Chernomordik