feradz
feradz

Reputation: 1362

Get currently logged in user id in controller constructor ASP.NET 5 MVC6

In MVC5 I was initializing the ID of the currently logged in user to a private filed by overriding the Initialize method in the controller.

public class BaseControllerConstructor: Constructor
{
    protected UserProfile _currentUserProfile;

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        if (User.Identity.IsAuthenticated)
        {
            _currentUserId = User.Identity.GetUserId();
            _currentUserProfile = LoadUserProfile(_currentUserId);
        }
    }
}

In MVC6 controllers do not have Initialize.

When I try to get the ID of the currently logged in user in the constructor, the User and the HttpContext are null.

public BaseControllerConstructor()
{
    // HttpContext is null      
    string _currentUserId = HttpContext.User.GetUserId();
    _currentUserProfile = LoadUserProfile(_currentUserId);
}

How can I achieve this in MVC6? Specifically: How can I get the user ID of the currently logged in user and initialize _currentUserId in the BaseControllerConstructor?

Then in the Controller action just call:

class Controller: BaseControllerConstructor
{
    public ActionResult Action()
    {
        foo(_currentUserProfile);
    }       
}

Update: I solved this using dependency injection. Please, see my answer below.

Upvotes: 4

Views: 3483

Answers (1)

feradz
feradz

Reputation: 1362

I have solved this using dependency injection and IHttpContextAccessor class to access HttpContext.User.

Implement service which is registered as Startup.cs.

// The interface for the service.
public interface IAccountService
{
    User CurrentUser { get; }
    string CurrentUserId { get; }
}

// The class which implements the interface
public class AccountService : IAccountService
{
    private IHttpContextAccessor _httpContextAccessor;

    // This is a custom services which has access to the business model and the data model
    private IUserService _userService;
    private string _currentUserId;
    private User _currentUser;

    public AccountService(IHttpContextAccessor httpContextAccessor, IUserService currentUser)
    {
        _httpContextAccessor = httpContextAccessor;
        _coreServiceProvider = coreServiceProvider;
        _currentUserId = null;
        _currentUser = null;
    }

    public User CurrentUser
    {
        get
        {
            if (_currentUser != null)
            {
                return _currentUser;
            }

            if (string.IsNullOrEmpty(_currentUserId))
            {
                // Get the user ID of the currently logged in user. 
                // using System.Security.Claims;                    
                _currentUserId = _httpContextAccessor.HttpContext.User.GetUserId();
            }

            if (!string.IsNullOrEmpty(_currentUserId))
            {
                _currentUser = _userService.Find(_currentUserId);
                if (_currentUser == null)
                {
                    string errMsg = string.Format("User with id {0} is authenticated but no user record is found.", _currentUserId);
                    throw new Exception(errMsg);
                }
            }

            return _currentUser;
        }
    }

    public string CurrentUserId
    {
        get
        {
            if (!string.IsNullOrEmpty(_currentUserId))
            {
                return _currentUserId;
            }

            // Get the user ID of the currently logged in user. 
            // using System.Security.Claims;
            _currentUserId = _httpContextAccessor.HttpContext.User.GetUserId();

            return _currentUserId;
        }
    }
}

Register the services in class Startup method ConfigureServices

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        // Register UserService a custom class which has access to the user profiles
        // This is injected.
        services.AddScoped<IUserService, UserService>();

        // Register the IAccountService which is injected in the controller
        services.AddScoped<IAccountService, AccountService>();
    }
}

Upvotes: 4

Related Questions