Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.net mvc 4 how to use WebSecurity.createUserAndAccount with custom field

I have a problem with I create a custom field in UserProfile table.like

public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public int? AddressId { get; set; }
        public int? UserDetailId { get; set; }
        public string UserName { get; set; }


        public UserDetail UserDetail { get; set; }


    }

   public class RegisterModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }

        public virtual UserDetail UserDetail { get; set; }

    }

     public class UserDetail 
     {
         public int Id{get;set;}
         public string FirstName{get;set;}    
         public string LastName{get;set;} 
     }

And I also added UserDetail to DbContext class

  public DbSet<UserDetail> UserDetails{get;set;}

The Problem is when I use

Web  WebSecurity.CreateUserAndAccount(model.UserName, model.Password, 
                        new { UserDetail = new UserDetail ()
                        }, false);

It always comes up with some error like :No mapping exists from object type... But If I define a simple type (like string, int) instead of UserDetail, it works fine.

Anyone can help me solve this problem? Thanks very much!!

like image 809
anary Avatar asked Mar 12 '13 09:03

anary


2 Answers

I had a similar problem to this and got it work by:

combine UserDetail and UserProfile to something along this line:

public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string FirstName{get;set;}    
    public string LastName{get;set;}
}

update your [HttpPost] Register

WebSecurity.CreateUserAndAccount(model.UserName, model.Password, 
   propertyValues: new { FirstName= model.FirstName, LastName = model.LastName}, false);

don't forget to add the new fields into your RegisterModel as needed

public class RegisterModel
{
    ....
    public string FirstName{get;set;}    
    public string LastName{get;set;}
}

hope this works for you

like image 52
Viranya Komphasouk Avatar answered Oct 21 '22 07:10

Viranya Komphasouk


I think you are looking to do this.

UserDetail

public class UserDetail 
 {
     //This is property mapping, UserId will be the same as the Membership UserId and UserProfile UserId
     [Key]
     [ForeignKey("UserProfile")]
     [HiddenInput(DisplayValue = false)]
     public int UserId { get; set; }

     public string FirstName{get;set;}    
     public string LastName{get;set;}

     public UserProfile UserProfile { get; set; } 
 }

RegisterModel

public class RegisterModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    [Required]
    public string FirstName{get;set;}

    [Required]   
    public string LastName{get;set;}
 }

Register Action

//
    // GET: /Account/Register

    [AllowAnonymous]
    public ActionResult Register()
    {
        return View();
    }

    //
    // POST: /Account/Register

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model)
    {
        if (ModelState.IsValid)
        {
            var db = new UsersContext();
            // Attempt to register the user
            try
            {
               var userProfile = WebSecurity.CreateUserAndAccount(model.UserName, model.Password, null, false);

                //var userProfile= db.UserProfile.SingleOrDefault(u => u.UserName == model.UserName);

                if (userProfile!= null) //This way Userdetail is only created if UserProfile exists so that it can retrieve the foreign key
                {
                    var userDetail = new UserDetail
                                           {
                                               UserProfile = userProfile,
                                               FirstName = model.FirstName,
                                               LastName = model.LastName
                                           };                                                

                    db.UserDetails.Add(userDetail);
                    db.SaveChanges();
                }                    
            }
            catch (MembershipCreateUserException e)
            {
                ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

Edit

Depending on how you have set up your Context and repositories, you will need something like below for each of your POCO classes

    public DbSet<UserProfile> UserProfiles { get; set; }
    IQueryable<UserProfile> IDataSource.UserProfiles
    {
        get { return UserProfiles; }
    }

In addition to SimpleMembership tables, you will need to add the following to your context for many-to-many between Membership and Roles

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Membership>()
          .HasMany<Role>(r => r.Roles)
          .WithMany(u => u.Members)
          .Map(m =>
          {
              m.ToTable("webpages_UsersInRoles");
              m.MapLeftKey("UserId");
              m.MapRightKey("RoleId");
          });
    }
like image 38
Komengem Avatar answered Oct 21 '22 07:10

Komengem