5

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.

9
  • Could you please submit your DbContext and ApplicationUser codes? Commented Feb 20, 2016 at 15:15
  • Why you added properties like ID, Email, Password, ... ? By inheriting from IdentityUser your user object already has. Also when and in which line you get the error? Commented Feb 20, 2016 at 15:27
  • 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: stackoverflow.com/questions/28149599/… Commented Feb 20, 2016 at 21:44
  • "Name cannot be null or empty." comes from if (!ModelState.IsValid)? Commented Feb 26, 2016 at 18:59
  • 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). Commented Feb 27, 2016 at 0:25

4 Answers 4

0

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).

Sign up to request clarification or add additional context in comments.

9 Comments

But UserName and Email are both fields that I'm using from IdentityDbContext which has those two fields so they should be present, no?
Fields are present in entity types (such as users), not context types (such as IdentityContext).
Yeah sorry that should be 'IdentityUser'. I'm using Email and UserName from IdentityUser.
You need to explicitly map them; mapping inherited from a base class are ignored by Entity Framework.
How would I go about mapping IdentityUser fields to my own entities? Taking public partial class users as the base.
|
0

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

Comments

0

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();

1 Comment

Thanks, the moment I have the time I'll have a look!
0

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
        };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.