2

As you know Validation is very important for a mvc website. As i understand you can make validation in four level. Confusion begins here? Should i use just ViewModel validation or may be ViewModel and Model validation but not HTML attributes or may be all. Using all validation methods makes code complex, hard to read models and viewmodels but solid. Using just viewmodel or model validation makes insecure. Imagine you're building a project at least 300 - 500 models, and view models. What would be your approach?

HTML Attribute

<input type="text" required>

ViewModel Dataannotations

[Required(ErrorMessage="You must enter your name")]
public string Name {get; set;}

jQuery

$("#someForm").validate()

Model Validation & DataAnnotations

[Required(ErrorMessage="ENTER YOUR NAME")]
public string Name {get;set;}

or

public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    //This is related to my architecture. Domain model inherits IValidateObject and overrides it. No big deal. This method raises when dbContext.SaveChange() method is in action
    if(Name.Length == "Admin")
    {
       yield return new ValidationResult("You can't use a reseved name.", new[] {"Name"});
    }
}
Murat
  • 149
  • 1
  • 16
  • I always do client side(Utilize html5 validation attributes and maybe javascript) and viewModel Validation – dansasu11 Oct 06 '15 at 10:55
  • How about Model Validation? This can be done if project only developed by you i think like @Coulton said down – Murat Oct 06 '15 at 11:44

3 Answers3

1

I recommend to do client side validation (HTML & Javascipt) and validate the entities that are stored in the database.

The HTML & Javascipt validation gives the user fast feedback and improves user experience when using your application. You should never forget that any client input against your website is unsafe and you can not trust that data.

The entity validation should be also be done, because if you have another API you have to ensure no invalid data is stored in the DB.

CodeTherapist
  • 2,776
  • 14
  • 24
  • You say HTML Attributes & Javascript and add entity validation but not viewmodel. Reasonable, but this makes ModelState.IsValid() unnecessary so Controller will map model to entity (may be other operations as well) and then validate and returns validation errors. Does this approach creates extra workload on server. By the way i can disable javascript and HTML attributes or manipulate the data using fiddler may be? – Murat Oct 06 '15 at 08:04
  • If you decorate your viewmodel with attributes, this will build up some validations with Js. The attr `Required` will add html attributes and the Js will use that information to provide unobstrusive validation (http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html). All the validation possibilities are for different purposes.. – CodeTherapist Oct 06 '15 at 08:11
  • I would also do the ViewModel validation as it introduces an easy way to check that the values passed from your view (posted) are valid. – Carles Company Oct 06 '15 at 10:27
1

The simple answer is:

It depends on how you have your application laid out and who the code will be used and reused by.

The long answer could be:

Client side validation, View Model validation, Model validation can all be performed at different points within your application and serve specific purposes depending on how you use/reuse your code. More below...

Model validation

I assume by this you mean the validation of models that are mapped to and sent to your service layer for processing? I'll assume yes for now...

If your service layer is only used by a single application (your application) and will never be reused by another application or by another developer, web/windows service or other, then you may be able to get away with not having validation in your service layer and you can rely purely on your View Model validation to protect your service layer. This is because there is only a single point that data will be coming and hitting your service layer.

However, if your service layer will be reused by another application or used by another developer it's helpful to perform the validation checks in there because it means that your service layer is bulletproof will provide other developers that use your service methods with useful validation information.

Bare in mind that if you don't add validation into your service layer and you ever want to allow other's to use it at a later date, you will need to go through and add the validation and this could be more difficult and time consuming at a later date. Your best bet is to build up the validation in your service layer as you're going along.

View Model validation

If you have decided at this point that you're not going to perform validation in your service layer, or that you need to perform validation that is specific to one or more pages or the service layer validation doesn't produce friendly validation messages for your application users, then you'll find that you need to perform view model validation.

How you perform your View Model validation is up to you. I personally don't perform validation within the Validate() method of IValidatableObject because it is only called when the validation attributes return no errors unless you use a custom model binder and I like to bring back all of the model errors all at once. For this reason, if there is any additional validation that is beyond the limits of what can be performed by the validation attributes (or custom validation attributes), I tend to perform it within the controller and this will go some way towards prevent your 'hard to read' view models, here's an example:

// Validate a field
if (string.IsNullOrWhiteSpace(viewModel.Name))
{ 
    // Add a validation error
    this.ModelState.AddModelError("FieldName", "This is an error");
}

if (this.ModelState.IsValid())
{
    // Do something...
}

Client side validation

This isn't required, but it's a nice to have as it prevents unnecessary load on your server by performing validation at the earliest opportunity using the client's processing power. But as already stated - it cannot be relied upon. It can be disabled or circumvented and your application can still be 'posted' to from anywhere outside of your application.

If you don't want to work too hard at it, just install the unobtrusive validation Nuget package into you MVC project and use the validation attributes that are provided by default and use the @Html. helper methods within your views. This will activate at least basic client side validation for you but only to the extent provided by the built in validation attributes.

Community
  • 1
  • 1
Luke
  • 22,826
  • 31
  • 110
  • 193
  • Yes you certainly could use `FluentValidation` for Model validation within your service/business layer. – Luke Oct 06 '15 at 11:23
  • This is acceptable. `Model` needs to be validated heavily because i'm workin on a large project. May be i can use _FluentAPI_ instead of property based `Dataannotations` so my entities stays much cleaner. `ViewModel` also needed to be validated but a little bit different. ViewModel validation includes View based specific validations. It is close to the entity rules but how close? Think that, `Name` property marked as `[Required]` in entity(model), should i also need to mark in ViewModel's `Name` property. IMHO Yes! – Murat Oct 06 '15 at 11:29
  • The only problem that I can see with that is that your FluentApi (on your ViewModels) may not tie in with MVC and the automatically generated client side validation. I don't think that you should obsess too much over your `ViewModel` objects being __too clean__, because they only serve one purpose anyway (1:1 to your views). Whereas, it is more important for `Model`s to be clean especially if they are reused throughout your application or used in multiple calls to your service layer. – Luke Oct 06 '15 at 11:34
  • When i said _"using FluentApi"_ i meant to use it for Model with Configuration classes. I know i'm a little bit obsessed but just searching for a best practice but looks like this is the way. At the end of the day this depends of how large the project is. – Murat Oct 06 '15 at 11:41
  • Oh sorry, yes I know what you're saying, for Entity Framework? Yes of course use Fluent API... That's what I use instead of the data annotations. I would say that the same applies to your domain models, they don't need to be too clean because they should only serve a single purpose... for retrieving and sending data to the database. [You should use DTOs for communication between layers imho and not your domain objects.](http://stackoverflow.com/questions/32889748/how-to-completely-decouple-view-and-model-in-mvc/32890875#32890875) – Luke Oct 06 '15 at 12:40
  • If you only decorate your domain models with their validation information as it relates directly to their storage limitations in the database then you're doing pretty well for 'cleanliness'. – Luke Oct 06 '15 at 12:42
0

I'll prefer using ViewModel DataAnnotations for client side. This makes things simple, and is customizable. Since I cannot completely trust/rely upon client side, I'd also validate ViewModel inside my controller's action (eg: if(ModelState.IsValid())) to make sure Model is in expected valid state, and no one tried to mess and forcefully posted.

Zeeshan
  • 2,884
  • 3
  • 28
  • 47
  • `ModelState.IsValid()` method is for validating the View Model. – Luke Oct 06 '15 at 10:49
  • @Coulton yes, exactly. Is there any mistake in my answer, or my concept? According to my understanding, you can always perform `ModelState.IsValid()` check in your `[Post]` action. isn't it? – Zeeshan Oct 06 '15 at 10:51
  • @Zeeshan You mistyped i think. Change "I'd also validate Model inside..." to "I'd also validate ViewModel inside...". – Murat Oct 06 '15 at 10:56
  • Yeah that's right, ModelState is for recording the validation state of values posted into your `[HttpPost]` controller actions. It's just that you made a distinction between validating your `ViewModel` one way and your `Model` using `ModelState`. I would personally say that validation of your `Model` should performed outside of the `System.Web` namespace in which `ModelState` resides. – Luke Oct 06 '15 at 10:57
  • @Coulton , @ Murat, Thanks – Zeeshan Oct 06 '15 at 10:59