HttpContext Header - c#

I have created this class for getting the Header value from requests.
public class AuthenticationHeader
{
private static IHttpContextAccessor _httpContextAccessor;
public AuthenticationHeader(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string AuthHeader => _httpContextAccessor.HttpContext?.Request.Headers["Authorization"];
}
and that I have registered that in my startup.cs like this
services.AddSingleton<AuthenticationHeader>();
And its been injected into my other classes like this.
public BaseClient(HttpClient client, ILogger<BaseClient> logger, AuthenticationHeader authHeader)
{
_client = client;
client.BaseAddress = new Uri("yrl");
client.DefaultRequestHeaders.Add("Accept", "application/json");
_logger = logger;
AuthHeader = authHeader;
}
Now as I have registered that as Singleton. So when call my Api for first time and provide the Authorization value in header the api is called successfully but the issue is when i pass empty Authorization header it still call's api successfully as it is storing old header value due to Singleton. How can I fix this? Is there any otherways to do what I am doing.

Try using HttpClientFactory, that was added Asp.Net Core 2.1, in conjunction with HttpMessageHandler to achieve what you are trying to do.
You can register the HttpClient in ConfigureServices method
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<BaseClient>(client =>
{
client.BaseAddress = new Uri("yrl");
client.DefaultRequestHeaders.Add("Accept", "application/json");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});
}
With the above code in place, your BaseClient will receive the HttpClient instance via DI.
In order to validate/inspect the AuthHeader you can configure the HttpMessageHandler for the registered HttpClient. The code for the message handler is simple like below:
public class AuthHeaderHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (!request.Headers.Contains("Authorization"))
{
return new HttpResponseMessage(HttpStatusCode.Forbidden)
{
Content = new StringContent("No Authorization header is present")
};
}
return await base.SendAsync(request, cancellationToken);
}
}
In order to register the above handler, your code will look like below:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<AuthHeaderHandler>();
services.AddHttpClient<BaseClient>(client =>
{
//code omitted for brevity
...
})
.AddHttpMessageHandler<AuthHeaderHandler>();
}
You can inject whatever you need inside the message handler if needed. However, no need to inject the IHttpContextAccessor in the BaseClient. To read more about HttpClientFactory and HttpMessageHandlers please see this link and this. I hope this helps.
UPDATED ANSWER
Please have a look at the more concrete example of HttpMessageHandler that uses the IHttpContextAccessor and modifies the HttpRequestMessage i.e. adds the Authorization header before the call is made. You can modify the logic as per your need.
public class AuthHeaderHandler : DelegatingHandler
{
private readonly HttpContext _httpContext;
public AuthHeaderHandler(IHttpContextAccessor contextAccessor)
{
_httpContext = contextAccessor.HttpContext;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (_httpContext != null)
{
var accessToken = await _httpContext.GetTokenAsync(TokenKeys.Access);
if (!string.IsNullOrEmpty(accessToken))
{
// modify the request header with the new Authorization token
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
}
return await base.SendAsync(request, cancellationToken);
}
}
UPDATED ANSWER 2
Please have a look at the simple solution that I have uploaded to GitHub. The solution is even simpler than I originally suggested. As you are not integrating any identity-based Authentication/Authorization, you can simply use a CustomActionFilter, I called it ValidateAuthHeader, to check if the AuthHeader is present or not and return the usual 403 if absent.
Within the ValidateAuthHeader, I have utilised the middleware code that you posted earlier. You can then simply add this attribute on the ActionMethods or Controllers which require this check.
Please have a look at the DataController and ValuesController. The DataController will receive the typed HttpClient that will be used to call the values endpoint. ValidateAuthHeader is present on the GetValues and will check for the AuthHeader. If it's absent it will generate the error.
[Route("api/[controller]")]
[ApiController]
public class DataController : ControllerBase
{
private readonly MyHttpClient _client;
public DataController(MyHttpClient client)
{
_client = client;
}
[ValidateAuthHeader]
public async Task<IActionResult> GetValues()
{
var response = await _client.GetAsync("api/values");
var contents = await response.Content.ReadAsStringAsync();
return new ContentResult
{
Content = contents,
ContentType = "application/json",
StatusCode = 200
};
}
}
The rest of the flow is the same as I originally suggested. The call will be passed through the AuthHeaderHandler which is an HttpMessageHandler for the registered MyHttpClient. Please have a look at the Startup.cs.
The handler will retrieve the HttpContext via HttpContextAccessor and will check for the AuthHeader. If present, it will add it to the RequestMessage parameter.
I hope this helps. Feel free to ask any questions that you may have.
Setting Auth Header without using HttpMessageHandler
Modify the MyHttpClient and add a public method called SetAuthHeader
public class MyHttpClient
{
private readonly HttpClient _httpClient;
public MyHttpClient(HttpClient client)
{
_httpClient = client;
}
public void SetAuthHeader(string value)
{
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", value);
}
}
Then call this method in your action method as you will have the AuthHeader in the HttpContext.Request at that point
[ValidateAuthHeader]
public async Task<IActionResult> GetValues()
{
var authHeader = Request.Headers["Authorization"];
_client.SetAuthHeader(authHeader.First());
var response = await _client.GetAsync("api/values");
var contents = await response.Content.ReadAsStringAsync();
return new ContentResult
{
Content = contents,
ContentType = "application/json",
StatusCode = 200
};
}
Remove the AuthHeaderHandler registration and delete the AuthHeaderHandler.

Related

Scoped service creating two different instances for a request

I'm fairly new to Asp.Net core 6 and am working on an GraphQL API that receives a bearer token in the request. The API then invokes another Web API and passes the same bearer token in the header. Below is what my code looks like-
Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<HeaderHandler>();
builder.Services.AddScoped<TokenContainer>();
//builder.Services.AddScoped<IFooGateway, FooGateway>();
builder.Services.AddHttpClient<IFooGateway, FooGateway>((c) =>
{
c.BaseAddress = new Uri(builder.Configuration["FooApiUrl"]);
})
.AddHttpMessageHandler<HeaderHandler>();
builder.Services.AddTransient<GraphApiService>();
var app = builder.Build();
app.UseMiddleware<HeaderMiddleware>();
app.MapGraphQL();
app.Run();
HeaderMiddleware.cs
public class HeaderMiddleware
{
//TokenContainer _tokenContainer;
private readonly RequestDelegate _requestDelegate;
public HeaderMiddleware()
{
}
public HeaderMiddleware(RequestDelegate requestDelegate)
{
_requestDelegate = requestDelegate;
//_tokenContainer = tokenContainer;
}
public async Task InvokeAsync(HttpContext context, TokenContainer tokenContainer)
{
var header = context.Request.Headers.Authorization;
tokenContainer.SetToken(header);
await _requestDelegate(context);
}
TokenContainer.cs:
public class TokenContainer
{
public string BearerToken { get; private set; }
public void SetToken(string token) => BearerToken = token;
}
HeaderHandler.cs:
public class HeaderHandler : DelegatingHandler
{
TokenContainer _tokenContainer;
public HeaderHandler()
{
}
public HeaderHandler(TokenContainer tokenContainer)
{
_tokenContainer = tokenContainer;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// for every request sent via the http client, intercept & add the bearer token header.
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", _tokenContainer.BearerToken);
// continue with request pipeline
return await base.SendAsync(request, cancellationToken);
}
}
FooGateway.cs:
public class FooGateway : IFooGateway
{
private readonly HttpClient _httpClient;
private readonly IConfiguration _configuration;
private readonly string _context = String.Empty;
public FooGateway(HttpClient httpClient, IConfiguration configuration)
{
_configuration = configuration;
_context = configuration["FooContext"];
_httpClient = httpClient;
}
public void DoSomething()
{
_httpClient.PostAsync("/blabla");
}
}
So, the idea was that the bearer token for every incoming request will be stored in a class called TokenContainer and the HttpHandler will add it to all the outgoing requests.
However, what is happening is that the token is stored in the TokenContainer but the HeaderHandler gets a different instance of TokenContainer in its constructor with its BearerToken property set to null.
Can someone please explain why the same instance of TokenContainer from the middleware is not being passed into the HeaderHandler?
The issue you are seeing is because the lifetime of the HttpMessageHandler is not the same as the lifetime of the request: usually, the same handler will be reused across many requests and be controlled separately on expiration timers and such.
You should not expect that a service injected into your message handler will be the same object that is injected outside it when it is registered as scoped.
https://andrewlock.net/understanding-scopes-with-ihttpclientfactory-message-handlers/#scope-duration-in-ihttpclientfactory
As the article suggests, to use the same scoped instance as you do outside the handler, you have to rely on IHttpContextAccessor to access the current HttpContext and fetch the service from there. So your handler implementation would look something like this:
public class HeaderHandler : DelegatingHandler
{
IHttpContextAccessor _httpContextAccessor;
public HeaderHandler()
{
}
public HeaderHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var tokenContainer = _httpContextAccessor
.HttpContext
.RequestServices
.GetRequiredService<TokenContainer>();
// for every request sent via the http client, intercept & add the bearer token header.
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", tokenContainer.BearerToken);
// continue with request pipeline
return await base.SendAsync(request, cancellationToken);
}
}
This should make sure that the TokenContainer instance is the same across your current request and http calls.
Remember that to add this functionality you need to add the accessor like this:
services.AddHttpContextAccessor();

How to Read Parameters sent to an Action Method (WebAPI) within a DelegatingHandler

I am using IHttpClientFactory for sending requests and receiving HTTP responses from an external APIs using Net Core 2.2.
I have implemented a DelegatingHandler to "intercept" my http request and add the Authorization header (Token). if token is not valid, It gets a new token and retry one more time.
Likewise, when I get a new token for the first time, I cache the token in-memory for further references. For caching the token I have created a dictionary that requires an accountID and the token.
The problem I have got is that the DelegatingHandler is registered in the Startup.cs class, but at that moment I do not have the accountID, I get the accountID as a parameter in the ActionMethod of the Controller. That action method is the one calling SendAsync and getting the token from the DelegatingHandler and so on.
I do not know, how I can inject that accountID into the DelegatingHandler after a request has been received in the controller.
I was trying creating a IClientCredentials interface and an implementation of that interface that can be instantiated in the controller and injected into the DelegatingHandler.
My Code looks like this:
The DelegatingHandler:
public class AuthenticationDelegatingHandler : DelegatingHandler
{
private readonly AccessTokenManager _accessTokenManager;
private readonly IClientCredentials _clientCredentials;
public AuthenticationDelegatingHandler(IHttpClientFactory httpClientFactory,
IOptions<AppSettings> appSettings, IClientCredentials clientCredentials)
{
_accessTokenManager = new AccessTokenManager(httpClientFactory, appSettings);
_clientCredentials = clientCredentials;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var clientCredentials = _clientCredentials.GetClientCredentials();
var accessToken = _accessTokenManager.GetToken(clientCredentials._accountID);
if (accessToken == null) {
accessToken = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
_accessTokenManager.AddOrUpdateToken(clientCredentials._accountID, accessToken);
}
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.access_token);
var response = await base.SendAsync(request, cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
{
var token = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
response = await base.SendAsync(request, cancellationToken);
}
return response;
}
}
Startup.cs like that:
services.AddScoped<IClientCredentials>(_ => new
ClientCredentials("au","123"));
services.AddHttpClient("myClient")
.AddHttpMessageHandler<AuthenticationDelegatingHandler>();
And The controller:
[HttpPost("{siteName}/{accountID}")]
public async Task<ActionResult<AirRequest>> Post(AirModel model, string
siteName, string accountID)
{
....
SetClientCredentials(siteName, accountID);
var clientJAAPI =
_httpClientFactory.CreateClient("myClient");
var responseclientJAAPI = await
clientJAAPI.SendAsync(request);
.....
}
private ClientCredentials SetClientCredentials(string siteName, string
accountID) =>
new ClientCredentials(siteName, accountID);
You can use HttpContext.Items to pass the data.
(Not tested, sent from mobile).
In controller:
this.HttpContext.Items["accountId"] = accountId;
In your Handler inject IHttpContextAccessor
var accountId = _httpContextAccessor.HttpContext.Items["accountId"];
IHttpContextAccessor not registered by default, but can be registered by one of components you are using. If you get an exception, register it explicetly in DI:
services.AddHttpContextAccessor();
If IHttpContextAccessor type is missing add Microsoft.AspNetCore.Http nuget.
The data will sit there untill end of the request.

Authentication per request using HttpClientFactory .net Core 2.1

How should I use HttpClientFactory to return an instance of HttpClient whose uri and credentials are determined at the point of the call?
The existing code looks like this:
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, password),
};
HttpClient client = new HttpClient(httpClientHandler);
client.BaseAddress = new Uri(_appSetting.ServiceURI);
your ConfigureServices method in Start up class
services.AddHttpClient("github", c =>
{
//c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
}).ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
UseDefaultCredentials = true,
Credentials = new NetworkCredential("", ""),
};
});
Your Controller will look like this
private readonly IHttpClientFactory _httpClientFactory;
public DataProController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient("github");
client.BaseAddress = new Uri("https://api.github.com/");
string result = await client.GetStringAsync("/");
return Ok(result);
}
You may not be able to set up Network Credentials at the run time when using httpclientfactory and may need to setup up in the startup class. you can find about this issue here.
https://github.com/aspnet/HttpClientFactory/issues/71
You can create an authentication delegating handler like this:
public class AuthenticationHttpMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Get the token or other type of credentials here
// string scheme = ... // E.g. "Bearer", "Basic" etc.
// string credentials = ... // E.g. formatted token, user/password etc.
request.Headers.Authorization =
new AuthenticationHeaderValue(scheme, credentials);
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
then add it to the HttpClient builder and to the DI container:
services
.AddTransient<AuthenticationHttpMessageHandler>()
.AddHttpClient("MyClient")
.AddHttpMessageHandler<AuthenticationHttpMessageHandler>();
then use IHttpClientFactory to create HttpClient instances.
The core advantage of this approach is that you clearly separate concerns. You don't touch the primary handler, you don't manage client creation manually, you utilize the whole power of the factory and its builder extension methods. The authentication handler is naturally injected in the pipeline and adds authorization to each request. This handler can be enhanced further by abstracting away the source of credentials and make the handler depend on some IAuthenticationProvider abstraction, which will require only DI configuration and not touching the HttpClient configuration code.
If you using the .net Dependency Injection you can add the configuration for one class into your setup code:
services
.AddTransient<DataLoader>()
.AddHttpClient<DataLoader>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
{
Credentials = new NetworkCredential(LoadUsernameFromConfig(), LoadPasswordFromSecureLocation())
});
Add now the DI will inject a HttpClient that uses this credential into the DataLoader class:
public class DataLoader
{
private readonly HttpClient httpClient;
public DataLoader(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task LoadData(string tableName)
{
var json = await httpClient.GetStringAsync("https://protected.example.com/json");
...
}
}
(I would not be able to come up with this code if I had not the answer from Imran Arshad: Thanks!)

Add multiple tokens into DefaultRequestHeaders.Authorization in HttpClient

The API I'm calling from my ASP.NET Web API app requires two tokens i.e. accessToken and userToken.
The following code is not working because it takes only the second token, not both. Looks like the second line is over-writing the first one.
How do I add multiple tokens to my request header?
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("APIAccessToken", "token1");
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("UserToken", "token2");
UPDATE:
Here's the way I set this up and it's not working. Basically, my API calls seem to go nowhere. I get no errors. Just no response.
First, I have the HttpClientAccessor that looks like this:
public static class HttpClientAccessor
{
private static Lazy<HttpClient> client = new Lazy<HttpClient>(() => new HttpClient());
public static HttpClient HttpClient
{
get
{
client.Value.BaseAddress = new Uri("https://api.someurl.com");
client.Value.DefaultRequestHeaders.Accept.Clear();
client.Value.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.Value.DefaultRequestHeaders.TryAddWithoutValidation("APIAccessToken", "token1");
client.Value.DefaultRequestHeaders.TryAddWithoutValidation("UserToken", "token2");
return client.Value;
}
}
}
I then have my ApiClient that will perform my API calls which looks like this:
public class MyApiClient
{
HttpClient _client;
public MyApiClient()
{
_client = HttpClientAccessor.HttpClient;
}
public async Task Get()
{
try
{
HttpResponseMessage response = await _client.GetAsync("/myendpoint"); // This is where it gets lost
var data = await response.Content.ReadAsStringAsync();
}
catch(Exception e)
{
var error = e.Message;
}
}
}
This is my controller action:
public class MyController : Controller
{
private readonly MyApiClient _client;
public MyController()
{
_client = new MyApiClient();
}
public IActionResult SomeAction()
{
_client.Get().Wait();
}
}
You are confusing the standard authorization header with custom headers
According to the linked documentation
Request Header
Add the generated tokens to the request headers "APIAccessToken" and "UserToken"
Example Request
APIAccessToken: zjhVgRIvcZItU8sCNjLn+0V56bJR8UOKOTDYeLTa43eQX9eynX90QntWtINDjLaRjAyOPgrWdrGK12xPaOdDZQ==
UserToken: 5sb8Wf94B0g3n4RGOqkBdPfX+wr2pmBTegIK73S3h7uL8EzU6cjsnJ0+B6vt5iqn0q+jkZgN+gMRU4Y5+2AaXw==
To get headers like above, add them to the client like below
_client.DefaultRequestHeaders.TryAddWithoutValidation("APIAccessToken", "token1");
_client.DefaultRequestHeaders.TryAddWithoutValidation("UserToken", "token2");
Based on shown update, the client is adding the headers every time the client is called. This should be in the value factory of the lazy client.
public static class HttpClientAccessor {
public static Func<HttpClient> ValueFactory = () => {
var client = new HttpClient();
client.BaseAddress = new Uri("https://someApiUrl");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("APIAccessToken", "token1");
client.DefaultRequestHeaders.TryAddWithoutValidation("UserToken", "token2");
return client;
};
private static Lazy<HttpClient> client = new Lazy<HttpClient>(ValueFactory);
public static HttpClient HttpClient {
get {
return client.Value;
}
}
}
The controller action also needs to be refactored to avoid deadlocks because of the mixing of async and blocking calls like .Wait() or .Result.
public class MyController : Controller {
private readonly MyApiClient _client;
public MyController() {
_client = new MyApiClient();
}
public async Task<IActionResult> SomeAction() {
await _client.Get();
//... code removed for brevity
}
}

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
}
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;
}
}
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.
You can try using an action filter in your controller. Try adding an override that looks something like this-
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);
}
The OnActionExecuting method is at the controller scope so you can have different logic for different controllers.
There's also an OnActionExecuted method override if you want to run code after your action method.
------edit--------------
As far as where to place your HttpClient code snippet, you can try this-
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);
}
So the HttpClient object along with the assignment of your baseUrl is established in OnActionExecuting. This code will run before any method returning a ActionResult in the controller you are refactoring. If you want to target some and not all methods, see the first example of OnActionExecuting above.
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();
}
Now your getuser method has an extra parameter ( HttpClient httpClient ).
why don't you move the code in Global asax or create custom Atribute?
here is one good link:
http://www.diaryofaninja.com/blog/2011/07/24/writing-your-own-custom-aspnet-mvc-authorize-attributes

Categories

Resources