Home > front end >  When is ActionController.HttpContext set?
When is ActionController.HttpContext set?

Time:02-24

I am trying to implement an ASP.NET Core MVC web app similar to Jason Taylor's CleanArchitecture design. In the WebUi "layer" I try to implement an abstraction of an IIdentityService in which I want to access the ClaimsPrincipal associated with the current HttpRequest.

After some digging through the source code on github, I found that the Controller.User property stems from ControllerBase.HttpContext? which is derived from ControllerContext which in turn is derived from ActionContext in which the HttpContext property is defined as

/// <summary>
/// Gets or sets the <see cref="Http.HttpContext"/> for the current request.
/// </summary>
/// <remarks>
/// The property setter is provided for unit test purposes only.
/// </remarks>
public HttpContext HttpContext
{
    get; set;
}

Here I am hitting a dead end. I assume the property is initialised by some middleware (ie. .AddAuthentication() / .AddAuthorization() from Microsoft.Identity), but I would like to confirm that, so I know how to get a reference to that object in my service.

Other sources of IPrincipals, from which ClaimsPrincipal I have found are

System.Web.HttpContext.Current.User
ClaimsPrincipal.Current
Thread.CurrentPrincipal

IHttpContextAccessor _httpContextAccessor;
var principal = _httpContextAccessor.HttpContext?.User;

with the documentation for IHttpContextAccessor here, but I cannot figure out which is the one Controller.User is pointing to.

CodePudding user response:

After being hinted in the right direction by @JHBonarius in the comments, I found a documented case in the official documentation

Use HttpContext from custom components

For other framework and custom components that require access to HttpContext, the recommended approach is to register a dependency using the built-in Dependency Injection (DI) container. The DI container supplies the IHttpContextAccessor to any classes that declare it as a dependency in their constructors:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();
builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<IUserRepository, UserRepository>();
In the following example:

UserRepository declares its dependency on IHttpContextAccessor. The dependency is supplied when DI resolves the dependency chain and creates an instance of UserRepository.

public class UserRepository : IUserRepository {
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserRepository(IHttpContextAccessor httpContextAccessor) =>
        _httpContextAccessor = httpContextAccessor;

    public void LogCurrentUser()
    {
        var username = _httpContextAccessor.HttpContext.User.Identity.Name;

        // ...
    } 
} 
  • Related