MVC Model Binding - asp.net-mvc

I am using the MVC validation library from link text. I chose this library because I am also using .NetTiers which generates all of the Validation Attributes using MS Enterprise Library Validation Blocks.
It works fine except that that model binding is automatically validating the object and populating the Validation summary. I believe this in normal behavior.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register([Bind()]NetTiersObject obj)
{
return View();
}
The validation library also has a method that is documented as follows:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register([Bind()]NetTiersObject obj)
{
try
{
obj.Validate<NetTiersObject>();
}
catch (EntityValidationException ex)
{
ViewData.ModelState.PopulateWithErrors(ex);
}
return View();
}
This also works fine.
My problem is that when using the validation library's method it duplicates the error messages. When just using the model binding the error messages appear strange. The errors have the property name in the message.
So, I think I should either need to format the model binding error messages or disable model binding altogether.
Any recommendation, help?
Thanks.

Have you try:
/*At the Point the ModelState should be Valid(TRUE)
because we still didn't enforce any validations */
var v = ModelState.IsValid;
try
{
obj.Validate<NetTiersObject>();
}
catch (EntityValidationException ex)
{
ViewData.ModelState.PopulateWithErrors(ex);
}
And check if v is True, it should be.
If it is true then obj.Validate<NetTiersObject>(); is doing something wrong because its the only populating the errors duplicated.
My problem is that when using the
validation library's method it
duplicates the error messages. When
just using the model binding the error
messages appear strange. The errors
have the property name in the message.
Its is weird because the modelBinding should not populate Model errors, at least if your are not using a custom Model Binding or trying to save into the DB without validating fields.

I found the answer to why my ModelState was invalid. The form elements do not match up to the model, that is the only way that the ModelState would be invalid immediately.
If I find more specifics I will update this post.

Related

Call ASP.NET's input validation after using ValidateInput(false)

When I bash my hands on special characters in the entry fields of my form, when I hit submit, all I get back is a blank page, as ASP.NET detected potentially malicious input and threw an error into my Event Log, all before reaching my MVC controller action.
I would much rather return an error to the user, so they don't just get a blank page. So I want to use ValidateInput(false) and then call the validator from inside my code, so I can send a response. How do I call the validator from an ASP.NET MVC action?
I am little confused with your question .Are you looking for invoking the code which does the model validation ? IF yes you can do that by checking the ModelState.IsValid property. If any of your validation fails, it will return false and in your view you will see the error messages. You can also specify some custom error message from your action method as well if you want to do so.
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
//Model validation is successful. Proceed to other stuff
//If you want to return some custom error message, do like this
ModelState.AddModelError("", "The user name is deactivated");
}
return View(model);
}
Do you want to validate input at server side?
You can use client side validation, you need to add regular expression attribute on your model property and set a nice error message for it. like below
[RegularExpression("your regex", ErrorMessage = #"please check your input .... ")]
public string MyInput { get; set; }

Attribute based error handling for ajax requests? (Is it worthwile?)

When I do Ajax.BeginForm posts to my actions returning a partial view I send error info in a ViewData item.
Currently in order to handle all errors I must wrap all of the method in a try catch statement.
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Save(int id, FormCollection form)
{
MyModel model;
try
{
...do stuff...
}
catch(Exception ex)
{
...log...
ViewData["ResultInfo"] = new ResultInfo(false, Resource.SAVE_NOT_SAVED, someErrorMessage);
}
return PartialView("Folder/SomeView", model);
}
I would like to do this with a custom HandleError attribute, but I realize that there must be many gotchas waiting to bite. Has anyone tried and want to share their experiences?
EDIT:
I've ended up doing error handling in a controller base class.
This ErrorHandlingController has 2 methods; RegisterErrorHandler and RegisterModel. If the error handler is found registered when an error is found in the base class OnException I just add the ResultInfo and marks the error as handled and uses the view and error caption I've set in RegisterErrorHandler.
This way it's very easy to get the model to the error handler and it's natural to use Resources directly since the error handler is registered as the first row inside the method as opposed to an attribute outside it.
I think the answer to this question will help you along: How to handle model state errors in ajax-invoked controller action that returns a PartialView.

MVC3 Service Layer Validation. Returning Exception, Custom Object, Model State Dictionary?

Just curious on your thoughts or experiences around service layer validation.
I have to process fairly standard validation such as "object with name property doesn't already exist", but I wasn't sure how to return these validation failures back to the controller.
My initial thought was to implement a standard List<ValidationError> but I've seen it done each and every way so was curious the pros/cons of each.
Thanks for any input.
If you go with System.ComponentModel.DataAnnotations entries you can (as you seem to know) decorate your properties with required and many more tags
public class Person
{
[Required(ErrorMessage="object with name property doesn't already exist")]
public string Name { get; set; }
}
although I personally use ViewModels rather than exposing domain mdoels to the view, your controller action can now do something like:
[HttpPost]
public ActionResult SavePerson(Person model)
{
if (ModelState.IsValid)
{
// your model validates - do things
return RedirectToAction("success view here");
}
return View(model);
}
This is one of the standard 'post' handler patterns in MVC. This is the simplest path to getting your object model validating in my opinion.
From there, there are a few other options - your domain object can implement IValidatedableObject and you can yield return the errors (see http://buildstarted.com/2010/09/20/mvc-3s-ivalidatableobject/ as an example).
I'd recommend not mixing the two though, as if you are using dataannotations and have even a single invalid property, the IsValid method on IValidatableObject will not be called.
From there, there's lots you can do with custom validation attributes (the extended version of IsValid seems to give you more flexibility http://msdn.microsoft.com/en-us/library/gg480674%28v=vs.98%29.aspx)
Hope some of the above helps - once you get past the basics there's a lot you can do with it and things like client validation of custom attributes etc. are all fun.
Cheers,
Terry
[edit to add:
After re-reading your post, it may be that you want to only validate at the service layer? If so, I've used the following approach:
public void Setname(string newName)
{
Validator.ValidateProperty(newName, new ValidationContext(this, null, null) { MemberName = "Name" });
Name = newName;
}
obviously your Name property would need a { get; private set; } for this, though you could always add the Validator.ValidateProperty into an extended setter for the public property either.
]
On a new project I'm working on (first time mvc) I've been using the ms code contracts (which throw exceptions) and do all the validation on my domain objects themselves. For things that can't be validated there (such as validations that require database access) I validate in my services and throw exceptions. Additionally like the poster above I have whole separate view models for everything that have data annotations validators on them. The exceptions bubble up and I catch them in the controller and append to the ModelState. There's a lot of overlap with those and the view model validation but it's not much extra effort and allows me to vary the validation per view and yet still have the "core" validations be required.
The book pro asp mvc 2 has another nice way - write a class that inherits Exception and contains a collection of errors. Then you do your validations, add to the collection then throw the exception then he catches it in the controller and copies over to ModelState. This method will let you catch ALL the errors in one exception instead of just one at the service layer.

MVC2: Using DataAnnotations to validate DataType

I am using Entity Framework + SQL Server DB and am using partial classes with DataAnnotations to validate data. For things like Required and Range, this works fine, but I am unable to get the DataType validators to work.
Here is an example of the (custom) annotation:
[DataTypeWholeNumberAttribute(ErrorMessage = "Zip must be a whole number")]
public object Zip{ get; set; }
...and the Controller Code...
[HttpPost]
public ActionResult Edit(NamedInsuredViewModel viewModel)
{
try
{ //breakpoint here (opening squiggly bracket) shows .Zip is already null
if (ModelState.IsValid)
...save, etc...
}
}
And I know what's happening: The DataType of Zip in the database is int, so the default validation is catching that and applying the generic error message "the value [x] is not valid for [FieldName]" before my validator can get to it (to prove this, I also added the same validator to a string field, and it works just fine). What I don't know is, how can I get around that (and no, I can't change the DB to use strings for everything)?
Some suggestions have been offered in this post (http://forums.asp.net/p/1608322/4162819.aspx#4162819), but so far nothing has helped.
Thanks in advance.
PS - is there really no way to validate a primitive DataType without creating a custom Attribute?
I think the error is to pass something called "viewModel" to a Edit Action.
ViewModel is intended for pass data to a view to render it.
When you submit a form the data have to be mapped to a entity not to a viewModel.
[HttpPost]
public ActionResult Edit(YourEntity entity)
{
try
{ //breakpoint here (opening squiggly bracket) shows .Zip is already null
if (ModelState.IsValid)
...save, etc...
}
}
Apply your custom validator to the class. Then pass in your class instance as the parameter for your validator instead of as a string. Then you can perform the validation on the appropriate property regardless of type.

What is ModelState.IsValid valid for in ASP.NET MVC in NerdDinner?

On the NerdDinner example of Professional ASP.NET MVC 1.0 there's a method to create a new dinner as copied bellow (page 89 of the free NerdDinner version).
There it checks ModelState.IsValid for true. It seems to check if the model is valid for the database (that is, it catches data type conversions, like dates with invalid format, but not business rules). Is that true?
When submitting the form, if you have an error in the date, ModelState.IsValid will be false and you'll get back an error, but only for the date because AddRuleViolations was never executed. If you remove the check for ModelState.IsValid completely, then you'll get all the errors (due to the exception), including a marking in the date when it is invalid. Then, why is the check for ModelState.IsValid there at all? Am I missing something?
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner) {
if (ModelState.IsValid) {
try {
dinner.HostedBy = "SomeUser";
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new {id = dinner.DinnerID });
} catch {
ModelState.AddRuleViolations(dinner.GetRuleViolations());
}
}
return View(dinner);
}
ModelState.IsValid tells you if any model errors have been added to ModelState.
The default model binder will add some errors for basic type conversion issues (for example, passing a non-number for something which is an "int"). You can populate ModelState more fully based on whatever validation system you're using.
The sample DataAnnotations model binder will fill model state with validation errors taken from the DataAnnotations attributes on your model.
From the Errata:
ModelState.AddRuleViolations(dinner.GetRuleViolations());
Should be:
ModelState.AddModelErrors(dinner.GetRuleViolations());
Reference: http://www.wrox.com/WileyCDA/WroxTitle/Professional-ASP-NET-MVC-1-0.productCd-0470384611,descCd-ERRATA.html
All the model fields which have definite types, those should be validated when returned to Controller. If any of the model fields are not matching with their defined type, then ModelState.IsValid will return false. Because, These errors will be added in ModelState.
Yes , Jared and Kelly Orr are right.
I use the following code like in edit exception.
foreach (var issue in dinner.GetRuleViolations())
{
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
in stead of
ModelState.AddRuleViolations(dinner.GetRuleViolations());

Resources