Extending ASP.NET Identity

2019-02-03 13:53发布

问题:

It seems this has been asked many times, in many ways, none of which seem to fit my exact situation.

Here's a line from my _LoginPartial.cshtml file:

@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })

See the part that says User.Identity.GetUserName()?

I want to change it to User.Identity.FirstName or User.Identity.GetFirstName().

I don't want it to say "Hello email address", but rather "Hello Bob"

My thought is that I'm simply wanting to show a new property (or method) on the Identity class. Obviously it must be more than that.

I've added the FirstName property and it is available in the AccountController.

public class ApplicationUser : IdentityUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

It does not get exposed in the _LoginPartial file. I want it exposed there!

Thank you for your help

回答1:

Even though your answer wasn't "exactly" what I wanted, your comments led me to this solution:

@using Microsoft.AspNet.Identity
@using YourModelnameHere.Models
@if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
    @Html.AntiForgeryToken()

    <ul class="nav navbar-nav navbar-right">
        <li>
            @{
                var manager = new UserManager<ApplicationUser>(new Microsoft.AspNet.Identity.EntityFramework.UserStore<ApplicationUser>(new ApplicationDbContext()));
                var currentUser = manager.FindById(User.Identity.GetUserId()); 
            }
            @Html.ActionLink("Hello " + currentUser.FirstName + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })

            @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" }) // I no longer need this ActionLink!!!
        </li>
    </ul>
    }
}

And in my IdentityModel.cs file, I added the two properties FirstName and LastName

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}


回答2:

I've done this by adding the First and Last Name to the claim when the user logs in, and then writing my own extension method.

When the user logs in, add the details you want to the set of claims (AccountController):

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    // Add the users primary identity details to the set of claims.
    var pocoForName = GetNameFromSomeWhere();

    identity.AddClaim(new Claim(ClaimTypes.GivenName, pocoForName));

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

The extension method, which just pulls the details from the set of claims for the user:

public static class IdentityExtensions
{
    public static IdentityName GetGivenName(this IIdentity identity)
    {
        if (identity == null)
            return null;

        return (identity as ClaimsIdentity).FirstOrNull(ClaimTypes.GivenName);
    }

    internal static string FirstOrNull(this ClaimsIdentity identity, string claimType)
    {
        var val = identity.FindFirst(claimType);

        return val == null ? null : val.Value;
    }
}

Now in the partial, just call the new extension method to get the details you want:

@Html.ActionLink("Hello " + User.Identity.GetGivenName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })

EDIT: updated to match more closely the original posters version of the SignInAsync() method

private async Task SignInAsync(ApplicationUser user, bool isPersistent) 
{ 
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);  

    var identity = await user.GenerateUserIdentityAsync(UserManager);
    //add your claim here

    AuthenticationManager.SignIn(new AuthenticationProperties() 
        { 
            IsPersistent = isPersistent 
        }, identity);
}


回答3:

answer updated for Asp .net Core ! Hope this save some time to other users.

@if (SignInManager.IsSignedIn(User)){

<form asp-area="" asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right">
    <ul class="nav navbar-nav navbar-right">
        <li>
            @{

                var currentUser = await UserManager.FindByEmailAsync(User.Identity.Name);
            }

            <a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello @currentUser.FirstName </a>
        </li>
        <li>
            <button type="submit" class="btn btn-link navbar-btn navbar-link">Log off</button>
        </li>
    </ul>
</form>

}