neomanni
neomanni

Reputation: 51

Thread.CurrentPrincipal Identity.Name is null in asp.net mvc 6 (vNext)

I am developing a web application using Asp.Net MVC6 (vNext), Identity 3.0.* beta3. This is 3-tier application with UI, Services and DB. I am able to sign in user with SignInManager class of Asp.net identity, and I am trying to retrieve user details with roles & claims in the service layer so that I can verify if user has permission to take certain actions.

How do we get Current username from current request principal identity in the service layer. In MVC 5, I have used Thread.CurrentPrincipal to do this. But in MVC6 Identity.Name of Thread.CurrentPrincipal is set to null.

Can someone let me know how I can do this? Also, if you have any better solution, please let me know.

Upvotes: 3

Views: 9849

Answers (3)

Avi Cherry
Avi Cherry

Reputation: 4096

If you've called AddIdentity() in your Startup.cs or wherever you configure your dependency injection, it will automatically register a singleton HttpContextAccessor as satisfying the IHttpContextAccessor service.

At this point, in your service layer, you can inject IHttpContextAccessor and retrieve the context from there. This assumes that you understand how the Dependency Injection system works and are using it to instantiate your service layer classes rather than just newing them.

If you want to be able to conveniently access the Id or Name of the ClaimsPrincipal that's exposed in the HttpContext make sure that you import System.Security.Claims so that you have access to the extensions that provide you with the GetUserName() and GetUserId() extension methods.

(This is up-to-date as of the beta4 packages that were released with VS2015 RC1)

Upvotes: 3

Hao Kung
Hao Kung

Reputation: 28200

Assuming you can pass access services in your layer, the equivalent of HttpContext.Current is IHttpContextAccessor.HttpContext which is a service exposed by the hosting layer.

Upvotes: 2

neomanni
neomanni

Reputation: 51

May be there is better way. But for now I am adding a custom middleware as in below code to inject ussername in current thread in startup.cs class. And in the service layer I will read it using Thread.GetData(Thread.GetNamedDataSlot("current-username")).

public class Startup {

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
    {

        //.... code

        app.UseIdentity();

        //... more code

        app.Use(async (ctx, next) =>
        {
            var httpContext = (ctx as HttpContext);
            if (httpContext.User.Identity.IsAuthenticated)
            {
                Thread.SetData(Thread.GetNamedDataSlot("current-username"), httpContext.User.Identity.Name);
            }
            await next();
        });

        //... more code

        app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });
            });

    }
}

Upvotes: 1

Related Questions