I have ViewModel that has inside a Model and some extra properties. There are validation on the model and on the property, but when executed, only validation on Model are checked, validation in the property is ignored.
The Model:
[MetadataType(typeof(Customer_Validation))]
public partial class Customer
{
}
public class Customer_Validation
{
[Required(ErrorMessage="Please enter your First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your Last name")]
public string LastName { get; set; }
[Required(ErrorMessage = "Sorry, e-mail cannot be empty")]
[Email(ErrorMessage="Invalid e-mail")]
public string Email { get; set; }
}
The ViewModel
public class RegisterViewModel
{
public Customer NewCustomer { get; private set; }
[Required(ErrorMessage="Required")]
public string Password { get; private set; }
public RegisterViewModel(Customer customer, string password)
{
NewCustomer = customer;
Password = password;
}
}
The Controller
public ActionResult Create()
{
Customer customer = new Customer();
RegisterViewModel model = new RegisterViewModel(customer, "");
return View(model);
}
[HttpPost]
public ActionResult Create(Customer newCustomer, string password)
{
if (ModelState.IsValid)
{
try
{
// code to save to database, redirect to other page
}
catch
{
RegisterViewModel model = new RegisterViewModel(newCustomer, password);
return View(model);
}
}
else
{
RegisterViewModel model = new RegisterViewModel(newCustomer, password);
return View(model);
}
}
The View
@using (Html.BeginForm())
{
<table>
<tr>
<td>First Name:</td>
<td>@Html.TextBoxFor(m => m.NewCustomer.FirstName)</td>
<td>@Html.ValidationMessageFor(m => m.NewCustomer.FirstName)</td>
</tr>
<tr>
<td>Last Name:</td>
<td>@Html.TextBoxFor(m => m.NewCustomer.LastName)</td>
<td>@Html.ValidationMessageFor(m => m.NewCustomer.LastName)</td>
</tr>
<tr>
<td>E-mail:</td>
<td>@Html.TextBoxFor(m => m.NewCustomer.Email)</td>
<td>@Html.ValidationMessageFor(m => m.NewCustomer.Email)</td>
</tr>
<tr>
<td>Password:</td>
<td>@Html.TextBoxFor(m => m.Password)</td>
<td>@Html.ValidationMessageFor(m => m.Password)</td>
</tr>
</table>
<input type="submit" value="Register" />
}
If I submit the form leaving Password empty it let go through. If I leave empty the Customer fields it do show the errors (except for the password field)
In ASP.NET MVC, ViewModels are used to shape multiple entities from one or more models into a single object. This conversion into single object provides us better optimization.
We can enable and disable the client-side validation by setting the values of ClientValidationEnabled & UnobtrusiveJavaScriptEnabled keys true or false. This setting will be applied to application level. For client-side validation, the values of above both the keys must be true.
ModelState. IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process. In your example, the model that is being bound is of class type Encaissement .
That's normal. Your POST controller action takes Customer
as parameter and not the view model. The validation is performed by the model binder, so when the model binder tries to bind the Customer object from request parameters it will invoke the validation. Your POST action needs to take the view model as parameter if you want the validation to be performed on this view model. Currently all you do with this view model inside the post action is to call the constructor and calling the constructor doesn't trigger any validation at all.
So your POST action should become:
[HttpPost]
public ActionResult Create(RegisterViewModel newCustomer)
{
if (ModelState.IsValid)
{
// code to save to database, redirect to other page
}
else
{
return View(newCustomer);
}
}
Notice how you don't need to pass the password as second action argument as it is already part of your view model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With