gtktuf
gtktuf

Reputation: 81

Can't save custom Application User fields to database with asp.net identity and MySql provider

In my case i have existing mvc project on azure-cloud.It was necessary to add a web api to identify external users, and it was also decided to use Mysql for storing information about the user. I configured the web api using the following instructions from microsoft: https://learn.microsoft.com/en-us/aspnet/identity/overview/extensibility/implementing-a-custom-mysql-aspnet-identity-storage-provider After provider was setted up, i used default asp.net web-api application, to set the rest fuinctionality. Here's my configurations:

IdentityModels.cs

using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using AspNet.Identity.MySQL;
using **.Web.App_Start;
namespace **.Web.Models
{
 
    public class CustomerPortalUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<CustomerPortalUser> manager, string authenticationType)
        {

            var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);

            return userIdentity;
        }
        public bool IsActive { get; set; }
        public string IdNumber { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string Address3 { get; set; }
        public string PostalCode { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Country { get; set; }
        public string City { get; set; }
    }
    public class PortalUserRole : IdentityRole
    {
        public PortalUserRole() : base() { }
        public PortalUserRole(string name) : base(name) { }
    }
    public class PortalUserDbContext : MySQLDatabase
    {

        public PortalUserDbContext(string connectionName)
        : base(connectionName)
        {

        }

        public static PortalUserDbContext Create()
        {
            return new PortalUserDbContext("PortalAuth");
        }
    }
}

AccountController.cs Register Method:

public async Task<IHttpActionResult> Register(RegisterBindingModel model)
        {
            BaseResponse response = new BaseResponse();
            response.IsSuccess = false;
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = new CustomerPortalUser() { 
                UserName = model.Email, 
                Email = model.Email,
                Address1 = model.Address1,
                Address2 = model.Address2,
                Address3 = model.Address3,
                PostalCode = model.PostalCode,
                City = model.City,
                IdNumber = model.IdNumber,
                LastName = model.LastName,
                FirstName = model.FirstName
            };

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

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }
            response.IsSuccess = true;
            return Ok();
        }

IdentityConfig.cs:

public class CustomerPortalUserManager : UserManager<CustomerPortalUser>
    {
        public CustomerPortalUserManager(IUserStore<CustomerPortalUser> store)
            : base(store)
        {
        }

        public static CustomerPortalUserManager Create(IdentityFactoryOptions<CustomerPortalUserManager> options, IOwinContext context)
        {
            var manager = new CustomerPortalUserManager(new UserStore<CustomerPortalUser>(context.Get<PortalUserDbContext>()));

            manager.UserValidator = new UserValidator<CustomerPortalUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = true,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true,
            };
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider = new DataProtectorTokenProvider<CustomerPortalUser>(dataProtectionProvider.Create("ASP.NET Identity"));
            }
            return manager;
        }
    }

And my Startup.Auth.cs:

public void ConfigurePortalAuth(IAppBuilder app)
{

    app.CreatePerOwinContext(PortalUserDbContext.Create);
    app.CreatePerOwinContext<CustomerPortalUserManager>(CustomerPortalUserManager.Create);



    app.UseCookieAuthentication(new CookieAuthenticationOptions());
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    PublicClientId = "self";
    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/portalApi/Token"),
        Provider = new ApplicationOAuthProvider(PublicClientId),
        AuthorizeEndpointPath = new PathString("/portalApi/Account/ExternalLogin"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
        AllowInsecureHttp = true
    };

}

But when i'm trying to register new user with my custom fields

public string IdNumber { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string PostalCode { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Country { get; set; }
public string City { get; set; }

User will be created with default identity values such a Password and UserName that i passed in request. But all my custom values will be equal NULL, instead of my values passed in the request. Also, if i will get user info like this:

 CustomerPortalUser user = await userManager.FindAsync(context.UserName, context.Password);

Even if custom values will be not null in database, they will be null in result above. Package used:

AspNet.Identity.MySQL 1.0.0.38741
MySql.Data 6.10.9
MySql.Data.Entity 6.10.9

Upvotes: 1

Views: 233

Answers (1)

Kia Kaha
Kia Kaha

Reputation: 1801

Why not try using the IdentityDbContext as base class for your DbContext where you can pass the IdenityUser and the IdentityRole models.

public class PortalUserDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>

I am not familiar with this MySQLDatabase class and where it comes from but it doesn't seem to accept your custom models. At least not shown as a snippet.

I am using ASP.Net Identity and EF with MySQL as well and as an adaptor I am happy with the Pomelo.EntityFrameworkCore.MySql NuGet package - if you have any issues with data on SQL level you might opt for this one.

Upvotes: 0

Related Questions