Reputation: 3397
Working in MVC3, c#
I am wondering about the 'hierarchy' of a model, class, db table and a partial class.
In the db I have a UserAccount table structured as:
USERACCOUNT: UserId, firstname, Lastname, Login, Password, email
In my project I have a model called UserModel. I am using it so i can decorate the properties with dataannotations. it is set up as the metadata type for the useraccount class, like so:
[MetadataType(typeof(UserModel))]
public partial class useraccount
{
}
public class UserModel
{
public int UserId { get; set; }
[Display(Name="First Name")]
[StringLength(20)]
[Required]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[StringLength(30)]
[Required]
public string LastName { get; set; }
[Display(Name = "Email Address")]
[StringLength(20)]
[Required]
public string email { get; set; }
[Remote("IsUserNameAvailable", "Validation")]
[Display(Name = "Choose a Login Name")]
[StringLength(40)]
[Required]
public string login { get; set; }
[Display(Name = "Choose a Password")]
[StringLength(64)]
[Required]
public string password { get; set; }
[Display(Name = "Enter Password Again")]
[StringLength(64)]
[Required]
public string confirmPassword { get; set; }
}
Notice in the database table there is a 'Password' column, but no 'confirmPassword' however in the UserModel, there is.
My thinking is the UserAccount class, using the UserModel class for metadata, should now contain a definition for 'confirmPassword'.
Here is the problem I am having. On the Register view, i am using the UserModel as the model, so at the top of the page I have:
@model OurAgreements.Models.UserModel
the problem comes in the controller when I try to save. This code:
public ActionResult Register(UserModel model)
{
var repo = new Repository();
if (ModelState.IsValid)
{
using (var db = new ouragreementEntities())
{
db.useraccount.Add(model);
db.SaveChanges();
}
return View();
}
gives the error, cant convert UserModel to useraccount. I can understand this, I am trying to put data into a table that doesn't match all the columns.
So then I figured I would change the model on the view to:
@model OurAgreements.Models.useraccount
because per my thinking, the useraccount class should be using the UserModel, but doing that gives an error, 'useraccount has no definition for 'confirmPassword'
So I am a bit stuck. i know I can switch back to using the UserModel as the model, then inthe controller I can build a new useraccount instance, and fill it with the data from the model, then save the instance to the database.
So I guess my question then, is why does useraccount not contain a definition for confirmPassword?
Upvotes: 0
Views: 235
Reputation: 561
First things first. Change the name of your classes. Use UserAccountMetadata / UserAccount. This makes things a lot easier to read and understand.
Also, use the compare attribute on the confirm password field so that you can be sure they match. The datatype attribute should be present on both password fields.
[DataType(DataType.Password)]
[Display(Name = "Confirm Password")]
[Compare("Password", ErrorMessage = "Password and confirm password must be same!")]
public string confirmPassword { get; set; }
The model your view uses should be UserAccount.
Before you pass your view model (UserAccount) to the method that saves it in the database, you need to map it to the object that the method takes, which looks like is your domain model object. You can do that manually but that is cumbersome. Use a mapping tool, such as AutoMapper to do that automatically for you. You can tell AutoMapper which fields in the UserAccount map to which fields in you domain model.
Upvotes: 1
Reputation: 39807
You were on the right path before by creating a View Model that contains your DataAnnotations and additional properties that are not in your database. This ViewModel and its related DataAnnotations help you to perform your business validation logic as well as allow you to map one or more tables worth of data to a single class for your view.
So, as to what I think your overall question is, why is there not a confirm password in the database? Why should there be? Having two copies of the same data in the database does not make sense in the realm of storing data.
The confirm password is a business logic / user input check to ensure that they did not 'fat finger' the password and lock themselves out of their account. Once you have confirmed that the password they entered is the one that they intended (password == confirmPassword), you hash the password and place it into the database.
Upvotes: 0