简体   繁体   中英

Implementing OWIN using existing Database name validation?

I wish to implement OWIN as per the example I could find here: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

However, since this way of working is new to me especially using my self created database I would like some guidance. I can submit my registration request without a problem.

The post takes me to the AccountController:

    [AllowAnonymous]
    [Route("Register")]
    public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        try { 
            var email = model.Email;
            var password = model.Password;

            var user = new users() {
                 Email = email,
                 PasswordHash = password,
                 Password = password
            };

            IdentityResult result = await UserManager.CreateAsync(user, model.Password);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }
        catch(Exception ex)
        {
            throw;
        }
    }

This triggers the below code:

    public ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

ApplicationUserManager:

public class ApplicationUserManager : UserManager<users>
{
    public ApplicationUserManager(IUserStore<users> store)
        : base(store)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<users>(context.Get<DaumAuctionEntities>()));
        var dataProtectionProvider = options.DataProtectionProvider;

        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = false,
            RequireDigit = false,
            RequireLowercase = true,
            RequireUppercase = true,
        };

        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<users>(dataProtectionProvider.Create("ASP.NET Identity"));
        }

        return manager;
    }
}

But for some weird reason I'm getting

 modelState: {undefined: ["Name cannot be null or empty."]}

Even though I don't use name anywhere?! Where is this name coming from?

So I presume I'm doing something wrong but it's hard to debug without a clear explanation on how to implement OWIN with an existing DB.

Below my context/entity and users table that I would like to use to store me user data.

context:

public partial class DaumAuctionEntities : IdentityDbContext<users>
{
    public DaumAuctionEntities()
        : base("name=DaumAuctionEntities")
    {
    }

    public DbSet<addresses> addresses { get; set; }
    public DbSet<auctions> auctions { get; set; }
    public DbSet<images> images { get; set; }
    public DbSet<users> users { get; set; }
}

users : IdentityUser:

public partial class users : IdentityUser
{
    public override string UserName
    {
        get
        {
            return Email;
        }
        set
        {
            Email = value;
        }
    }

    override public string PasswordHash
    {
        get
        {
            return Password;
        }

        set
        {
            Password = value;
        }
    }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<users> manager, string authenticationType)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
        // Add custom user claims here
        return userIdentity;
    }
}

public partial class users
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public System.DateTime CreatedDate { get; set; }
    public Nullable<System.DateTime> ModifiedDate { get; set; }

}

Edit:

If I add UserName back to my new users object before I try to call CreateAsync, the error is gone but I get another one instead:

"The specified type member 'UserName' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."

Edit II:

I also have this issue in the tutorial code! This is just a freaking bug in .NET?

Edit III

I tried to do an override as you can see in the partial class Users above. But I still have the same error.

The issue is due to the fact that I did not add UserName to my new user before I call UserManager.CreateAsync. If I add the UserName I have the exact same issue as this: MVC 5 IdentityDbContext and DbContext transactions

That issue seems to point to the fact that ASP.NET Identity is using the UserName property in a query, but Entity Framework compains that the property is not mapped to a database column in your Entity model (EDML).

I don't see many problems with your code

  1. Remove the users DbSet from your DaumAuctionEntities class (See this )
  2. Remove the Id property from your users class
  3. Set the CreatedDate property when you create a new users inside the Register method

Then you should be OK

Also,about:

Nope, it actually passes that. It comes from I believe the manager but whenever I try to debug that code the debugger states that it jumped over it (most likely due to the fact that it's an external library from Microsoft).

If you wrap the call with a try/catch you'll be able to see the error message

I got few issues with the code you have shared here but not exactly the same as you mentioned. I have shared the example on git for your reference. Try it by your self and let me know if you see any issues.

Git URL - https://github.com/JitJDN/OWINStack

See, code is still the same as yours:

var email = model.Email; var password = model.Password;

        var user = new users()
        {
            Email = email,
            PasswordHash = password,
            Password = password
        };

        IdentityResult result = await UserManager.CreateAsync(user, model.Password);

        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        return Ok();

I finally got it working.

In the end I had to add adjust the partial class Users (which is a table in my SQL database) so that UserName and Password override the fields of IDentityUser (so not like I did in my question):

public partial class users
{
    public int Id { get; set; }
    public string UserName {get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }    
    public DateTime? CreatedDate { get; set; }
    public DateTime? ModifiedDate { get; set; }
}

I then just had to pass the password and UserName when I created the user:

        var user = new users() {
             Email = email,
             UserName = email, 
             PasswordHash = password,
             Password = password
        };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM