How dynamically set validation attributes to a Model MVC 2? - model-view-controller

Lets says I have the following model
public class Person
{
[NameIsValid]
public string Name { get; set;}
public string LastName { get; set; }
}
I created a custom attribute NameIsValid for this model.
Lets says for ViewA I need the custom attribute validation in the model, but for ViewB I dont need this custom validation attribute.
How can I dynamically set or remove the custom attribute from the model when need it?
Thanks!

Don't put any validation in ViewB :
Client-side :
#Html.ValidateFor(x => x.Name)
Nor server-side :
if(ModelState.IsValid)
{...}

Related

Giving error while creating partial class

I am developing MVC application in which , I am trying to create the partial class of class generated by MVC application lets say Location class.
Now I want to create the partial class of Location class in new class file.
The below class code is auto genrated by MVC of Location code.
namespace CRM
{
public partial class Location
{
public int Id { get; set; }
public string Name { get; set; }
public string Remark { get; set; }
}
}
I have added new class file which contain the partial class of above file
namespace CRMEntities.Partial_Class
{
public interface ILocation
{
[StringLength(50, ErrorMessage = "Region can accept maximum 50 characters.")]
string Region { get; set; }
[Key]
int Id { get; set; }
[Required]
string Name { get; set; }
string Remark { get; set; }
}
public partial class Location : ILocation
{
}
}
Its giving the below error...
CRMEntities.Partial_Class.Location' does not implement interface member 'CRMEntities.Partial_Class.ILocation.Name
First, you don't need to do this, what I understand is you are trying to do validation right? Think about, the object generated by EF is not ViewModel, they are domain model. Data annotation should be in View Model, not domain model.
Most of cases, often mis-use is to use domain model as view model, but it is not correct much. Because sometime, view models need more than one domain model to provide data for your UI.
So for separation of concerns, you need to define your View Model different with domain model.
Example: you have Location class, you need to add LocationViewModel class and put data annotation in here.
You can map manually or use AutoMapper for mapping bettween View Model and Domain Model.
Another solution is you can use Fluent Validation, with this way, needless to have more partial class just for validation.
You don't show the definition of ILocation in your question, but the error says that the Location.Name property is declared differently than the ILocation.Name member.
Edit: Your two partial classes appear to be in two different namespaces, hence they are actually two entirely different classes, not two parts of the same class. That would explain the compiler error.
Having said that, I do agree with the other answer (+1!) that you should do your UI validation on a view model instead.

Failing to get unobtrusive client validation

I figured out that property i want to be validated has to have [Required] attribute in C#
(am i right?)
If so -my model is linq generated class - how to add this attribute?
You can do it a couple of ways:
If it's possible, make the field non-nullable in the database. This will make the field required at the data layer.
Create a partial class that adds a property to your model class. Use this property instead of the database-generated property.
For example:
public partial class YourEntity
{
[Required]
public string YourNewProperty
{
get { return this.TheRealProperty; }
set { this.TheRealProperty = value; }
}
}
Hopefully this helps
well, you could always make a new class, as a part of a Data access layer, with the same attributes, just put [required] where you want.
I believe your LINQ classes are partials. With MVC, you can use the "MetatDataTypeAttribute"
Like so
[MetadataType(typeof(UserMetadataSource))]
public partial class User {
}
class UserMetadataSource {
[HiddenInput(DisplayValue = false)]
public int UserId { get; set; }
}

ASP.NET MVC3 conditional validation - checkbox > editor

I would like to have a bool field and and a string field in my Model and not having any validation attributes on them.
But in the view I would like to have the required field validation on the Editor if the Checkbox is checked.
How do I do this please?
Thank you.
You can still use the data annotations attributes and follow any of this option.
Clear the errors from the modelstate dictionary for that field inside the action
Use the conditional validation library created by simon.
Ex.
public class ValidationSample
{
[RequiredIf("PropertyValidationDependsOn", true)]
public string PropertyToValidate { get; set; }
public bool PropertyValidationDependsOn { get; set; }
}

MVC3 / EF CustomValidator two fields in model

Using MVC3 and EF4.1 how do I validate on client and server more than one field in my view model?
I have a start date text box (that can be modified) and I have the original start date in a hidden field. When the user submits the form I want to check that the modied start date is no more than one month either side of the original start date.
I can't figure out how this can be done with DataAnnotation and CustomValidation (or maybe I'm going down the wrong road)? This is an example of whay I've been working with:
[MetadataType(typeof(Metadata.MyUserMetaData))]
public partial class MyUser
{
public System.DateTime DateOfBirth { get; set; }
}
Partial Class
public class MyUserMetaData
{
[CustomValidation(typeof(AmendedStartDate), "amendedstartdate", ErrorMessage = "Invalid date."]
public DateTime StartDate { get; set; };
public DateTime OriginalStartDate { get; set; };
}
Custom Validator
public class AmendedStartDate : ValidationAttribute, IClientValidatable
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// How do I get multiple field values from object value?
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(Modelmetadata metadate, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "amendedstartdate"
};
yield return rule;
}
}
I know I've still to add jQuery to the view for this validator.
Instead of using data annotations implement IValidatableObject on your model class - it is simpler and much more clear in scenarios with cross validation.
If you still want to use ValidationAttribute you have two parameters in the IsValid method:
value represents validated value of the property where the attribute is assigned
context is context in which the property is validated. It also contains ObjectInstance and ObjectType properties to access the whole model and its type so you can cast the instance and access other properties.
The question asked in MVC custom validation: compare two dates has an example of a validator which compares to a second value in the model. That should get you started.

How to bypass validation when using viewmodels for search filtering in ASP.NET MVC (3RC2)

I'm working on an ASP.NET MVC app (using MVC3 RC2). Say I have 2 entities, Product and Category. A Category must have a CategoryTitle, which is denoted via metamodel attributes like so:
public class CategoryModel
{
public int CategoryID { get; set; }
[Required("{0} is required.")]
public int CategoryTitle { get; set; }
}
There is also a relationship such that each Product has an association with Category. When searching Products, users must be able to filter the results by selecting a Category from a drop-down HTML select list. I've tried different ways of doing this, and the following seems to promote the most code reuse:
public class SearchModel
{
public CategoryModel Category { get; set; }
public string Keyword { get; set; }
}
public class ProductController
{
public ActionResult Search(SearchModel searchModel)
{
if (ModelState.IsValid)
{
// logic to return view with viewmodel
}
return HttpNotFound();
}
}
In the view, a drop-down list is rendered using the SearchModel, and it sends requests via HTTP GET in the form of /Product/Search?Keyword=my+keywords&Category.CategoryID=69. The SearchModel object is populated as intended, creating a new CategoryModel with CategoryID == 69.
The problem is that the ModelState.IsValid always returns false, since the Category.Title is null. What is the appropriate way to do this in ASP.NET MVC? Do I have to resort to creating a different SearchModel that doesn't have a CategoryModel instance?
The proper way to do this is to use view models instead of your models to and from the views. View models are classes which are specifically tailored to the needs of a given view: they contain only the properties required for the view and the validation attributes in the context of the given view. Thus you might have multiple view models for the same model. To map between the model and the view models you could use AutoMapper.

Resources