MVC how to disable the required validation for some controls - c#

I am creating a web application using MVC 4.
I have a few properties in my view model that has been decorated with the required attribute as shown,
[Required(ErrorMessageResourceName = "StateRequiredMessage", ErrorMessageResourceType = typeof(Resources.Agency.CreateEdit))]
public int? PostalAddressStateId { get; set; }
but then in my view, depending on what the user selects from a tick box, I disable some of the properties that have been tagged as required.
I disable the controls using jQuery:
$("#PostalAddressStateId").attr("disabled", true);
Then when I try to save, it says the value is required. How do I solve this?

Try
ModelState.Remove("PostalAddressStateId");
at your controller

Try this:
PostalAddressStateId.Attributes.Remove("Required");
You might need to set a boolean in javascript and send it back to the controller, the required attribute impacts your server side code as well.
In my opinion, a field like this shouldn't be marked as required unless it's always required. If this is in a viewmodel, then I'd probably remove the attribute and replace it with a custom attribute or some other way of determining that it's filled in when it must be and not filled in when it's not required.
More about attributecollections here:
http://msdn.microsoft.com/en-us/library/system.web.ui.attributecollection.remove(v=vs.110).aspx

I would check out MVC Foolproof Validation on CodePlex. You could use the RequiredIfTrue attribute that comes with Foolproof to solve the issue above.
http://foolproof.codeplex.com/

Related

Which part of the code shows validation errors after Post in asp.net MVC?

Let's say I have one view model. It has one required Name property. And I have disabled client-side validation. I have this code in my action method:
if (!ModelState.IsValid)
{
return View(model);
}
So, everything works fine. It will highlight the required field after post. But, I can't understand that which jQuery validaion function do this process? How, jQuery Validation detects that the form has been submitted once?
I want to find that code, because I want to change it slightly. For example, I have my own helpers, which has custom validation logic. For now, my custom helper validation are not showing after invalid Post. And, I want to add my logic to the built-in function, which I CAN NOT FIND ANYWHERE.
Firstly, if you have disabled client side validation, jquery validation has nothing to do with it (you have disabled it!). To briefly explain what happens when you post and return the view.
The DefaultModelBinder initializes a new instance of you model
The DefaultModelBinder then reads the form data (name/value pairs)
and if a property name matches one of the form data values, its
property is set (assuming its valid) and its value is also added to
ModelState. If the value is not valid, the property is not set but
its value is added to ModelState (the attemptedValue) along with
a ModelState error
When you return the view, your #Html.ValidationMessageFor() method
reads the ModelState values and if there is an error associated
with the property, the error message is added to the html generated
by the ValidationMessageFor() method and the relevant class name
(which highlights it) is added
You can inspect the source code for the DefaultModelBinder and ValidationExtensions if you want to see more detail of how these work.
As for "I want to find that code, because I want to change it slightly", then DONT. You have not indicated what you trying to do, or shown any code for your html helper extension method, but html helpers do not (and should not) contain validation logic. They are responsible for generating html based on a property and the validation attributes applied to that property.
If you have custom validation logic for a property, then you create an attribute that inherits from ValidationAttribute (and if you also want client side validation then it also needs to implement IClientValidatable). A good guide for creating your own validation attributes is this article.
Mvc has its own validation that is not server side and works with the data annotations you set on your model. On post it simply goes to the controller then checks the modelstate errors if its valid it runs your code in the function, if not it returns the model with its errors. If you had jquery validation it would never go to the controller in the first place. When server side validation is enabled the validation is done before the form is sent to the controller. Without jquery it is validated at the controller. If not what you're looking for please let me know

What does [Required] do?

I found nothing on the web what [Required] actually does. The msdn-article is not explorative at all.
static class Program
{
public static Main()
{
var vustomer = new CustomerClass();
}
}
public class CustomerClass
{
public string m_FirstName;
[Required]
public string m_LastName;
}
As far as i understand, that should throw an exception since m_LastName is required, but not set. But i don't get one. I don't get what it's good for and what this actually does.
RequiredAttribute, like all other attributes, does nothing by itself other than annotate something (in this case, a field of a type). It is entirely up to the application that consumes the type to detect the presence of the attribute and respond accordingly.
Your sample program does not do this, so the attribute does not have any visible effect. Certain frameworks such as ASP.NET MVC and WPF do check for and respond to the presence of the attribute.
This attribute is used by the Validator class to add validation errors based on any types that inherit from ValidationAttribute. This is used by MVC model validation, for example.
In C#, attributes are almost decoration to classes and properties.
Except for a few security related attributes, most do nothing. They are used by a higher-level framework to do something.
In the case of ASP.NET 4 MVC, only when the object is part of a request that attribute is used to generate an error.
If you want to use that attribute in any other environment, you must write code to inspect it.
It won't do anything from a plain old public static void Main()
Documentation on RequiredAttribute:
Specifies that a data field value is required.
However this validation is typically only performed in the UI layer. It is not "baked" into the constructor or other low-level usage. If you want to manually fire the validation you could do something like:
var customer = new CustomerClass();
var context = new ValidationContext(customer, serviceProvider: null, items: null);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(customer, context, results);
if (!isValid)
{
foreach (var validationResult in results)
{
Console.WriteLine(validationResult.ErrorMessage);
}
}
To add to the current answers, these are some of the practical uses I can think of out of my head:
Entity Framework use this to model the database as not nullable fields.
Javascript client side validation provides javascript libraries for checking if the input field has any data, else prevent the form submission avoiding unnecesary roundtrips to the server.
Server side validation (when doing model binding) also check when you are posting a model with that decorator that the attribute passed in is in the request. This determines if the model state should be set to an invalid state or not. (1)
There are also annotation for JSON.NET library that changes how the model is serialized/unserialized. I'm pretty confident (but not sure) that the Validate Schema of Json.net does take into consideration the 'Required' attribute when validating a schema.
Other attribute decorators are used on web services, but 'Required' is not one I know has it uses in this scenario.
Web api uses this attribute to mark the property as required on documentation help pages and model binding.
You can create your own application logic that can be aware of the 'Required' property. For example, on a view to mark the property with an * in the label if it's required.
This are some uses but you are not limited to them.
(1) Note: if your property is, for example, an int and you decorate it with Required, model state will never be on a invalid state. You should use Nullable properties for this use-cases.

How to add MetaData to a dynamically build MVC3 ViewModel?

One of the key features of a project I'm working on is the ability for the user to configure Forms (as in "Forms" to fill-up) based on a pool of pre-existing field types (well known types, for instance "user name", "date of birth" etc. but also "generic types" like "string", "DateTime" etc.).
We used to have a static ViewModel that worked fine for the "well known" types and looked like this:
public class UserInputModel
{
[StringLength(200)]
public string Name { get; set; }
[Required(ErrorMessageResourceName = "BirthDateEmptyError", ErrorMessageResourceType = typeof(Resources.ErrorMessages))]
public DateTime BirthDate { get; set; }
//Here comes a lot of other properties
}
All the known properties were listed and we were showing or hiding them given the context.
But the last requirement came and changed all that. The user shall now be able to add as many generic type fields as he wants. In order to do this, we decided to make this InputModel entirely dynamic. It now looks like this:
public class UserInputModel
{
// Each ModelProperty has an "Id" and a "Value" property
public ICollection<ModelProperty> Properties { get; set; }
}
This works like a charm. The razor view only has to iterates over the collection, create the corresponding controls for each property of the collection in a more than standard way:
#Html.TextBoxFor(m => m.Properties[index].Value);
... and we nicely get the data back as a filled form.
=> This works fine, but we don't have any client-side validation. For this, we would need some Metadata... which we don't have via annotations anymore since we're dynamically creating the model.
In order to provide those MetaData, I created a CustomModelMetadataProvider that inherits from DataAnnotationsModelMetadataProvider and registered it as the new ModelMetadataProvider in the Global.asax. The CreateMetadata() function gets called upon creation of the ViewModel, and that for each of the properties of my ViewModel... sofar so good.
Where the problem starts: in order to add some metadata to the current property, I first need to identify which property I am currently looking at ("Name" has a maxlength of 200, "date of birth" hasn't so I cannot assign a maxlength to every property per default). And somewhow I didn't manage to do that yet since all the properties have the same name Value and the same container type ModelProperty.
I tried accessing the container of the property via reflection, but since the ModelAccessor's target is the ViewModel itself (because of the lambda expression m => m.Properties), the following construct gives me the ViewModel as a whole, not just the ModelProperty:
var container = modelAccessor.Target.GetType().GetField("container");
var containerObject = (UserInputModel)container.GetValue(modelAccessor.Target);
I've been flipping this over and over but cannot find a way to identify which ModelProperty I have in hand. Is there a way to do this?
Update: after flipping this in every possible direction for a while, we finally went another way. We are basically using unobstrusive javascript to use MVC's validation capabilities without touching attributes nor metadata. In short, we add HTML attributes like value-data="true" (and all other required attributes) to the #Html.TextBoxFor() statements. This works wonderfully for all the atomic validations (required, stringlength etc.).
Tim, you can leverage what appears to be client-side validation through Ajax with the Remote attribute on your properties.
Basically, you'll need to set up a validation controller and then write some smarts into that controller. But at least you'd be able to write some helper methods and keep it all in one place. You would have a series of validators, based on the meta data that you are presenting to the end users, and each validator method would work for a particular type with good re-use.
The one pitfall to this approach would be that you would need to write a validation method for each type and condition that you want to support. Sounds like you're having to go down that road anyways, though.
Hope this helps.
See if this article help you: Technique for carrying metadata to View Models with AutoMapper.
Also use this one for ideas (custom model metadata provider): changing viewmodel's MetadataType attribute at runtime
Fluent validation is probably the best option for you in my mind, but its obviously up to you to select the best match among those above.
Update
Try use ModelMetadata and override ModelMetadataProvider: Dive Deep Into MVC: ModelMetadata and ModelMetadataProvider. This way you completely customize your model metadata (this replaces data annotations) and you have complete control on what is happening, rather than relying on ASP.NET MVC.
Another good place to look at it is Creating your own ModelMetadataProvider to handle custom attributes.
Hope this all is of help to you.

How to set/remove attributes dynamically in c#?

I am using from attribute validation in my project.
[Required(ErrorMessage = "DepartmentCode is Required")]
public string DepartmentCode { get; set; }
In some case DepartmentCode isn't required. How can I dynamically ignore Validation in my case?
Take a look at: Remove C# attribute of a property dynamically
Anyway I think the proper solution is to inherit an attribute from RequiredAttribute and override the Validate() method (so you can check when that field is required or not). You may check CompareAttribute implementation if you want to keep client side validation working.
Instead of dynamically adding and removing validation, you would be better served to create an attribute that better serves this purpose.
The following article demonstrates this (MVC3 with client-side validation too):
http://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx
I would remove the RequiredAttribute from your model and check it once you've hit your controller and check it against whatever causes it to not be required.
If it falls into a case where it is required and the value is not filled in, add the error to the ModelState manually
ModelState.AddModelError("DepartmantCode", "DepartmantCode is Required");
You would just lose the validation on the client side this way
I've got round this issue in the model, in some cases it's not ideal but it's the cheapest and quickest way.
public string NonMandatoryDepartmentCode
{
get
{
return DepartmentCode;
}
set
{
DepartmentCode = value;
}
}
I used this approach for MVC when a base model I inherited contained attributes I wanted to override.

Using Knockoutjs And Server Side Validation in .NET MVC2

I'm using MVC2.
Whats the recommended way of server side validation of forms when using knockout?
Currently, most of my forms are in partial views, which have a C# ViewModel with Validation Attributes. Something like this:
public class SomeThingViewModel
{
[Required]
public string Name { get; set; }
[Required]
public int Number{ get; set; }
}
So when the form gets submitted to the server, I get all the model errors and I can return the form with errors, which are displayed with something like: <%: Html.ValidationMessageFor(m => m.Name)%>. This is then reloaded into the element that holds the form on the main page so that the user can see the errors. This would kill any bindings I had with the form in knockout I would assume.
I'm not really sure how to go about this using knockout.
This can be tricky, but done right works like a breeze.
First, synchronize your viewmodels. What you have client-side in knockout you pass exactly to the server. Second, don't do server-side HTML with knockout. Create fields that are set server-side and read client-side that indicate the validity of each data field in your ViewModel.
So if your Model has a field Name, your ViewModel has Name and Name_ValidationResult, which is an enum that indicates whether or not the Name field is valid and why it's not. If your server-side validation fails, set your validation result fields and pass the whole server-side ViewModel back to the client to be re-set as the client-side ViewModel after the request completes. Basically, you a re-creating the ViewState portion of ASP.NET, but doing so in a format that will work with Knockout.js
On the client-side, you have error messages that only show based on values of the ValidationResult fields. So you might have a canned error message that states "The Name field must be set" that is only displayed if Name_ValidationResult has the value "Empty" (for example).
Basically, you actually use the MVVM pattern with a minor tweak to account for having to round-trip to the server.
So you are suggesting that I add ValidationResult fields in my C# ViewModel for each property. Then set the ValidationResult Properties in my controller when I check for the Model's validity. Then pass back the viewmodel as JSON? so that I can update my knockout viewmodel. This will require me to manually validate to some extent right? Or can I leverage the ModelState errors that I will end up with? – Blankasaurus
Bottom line is yes to all your questions.
In truth, I missed the fact that you were using DataAnnotations for your validation, or I'd have mentioned it. You should be able to leverage ModelState errors to set your validation results that you pass back to your knockout page.
The problem is that you're using two fundamentally incompatible technologies and hoping they'll play nice together, and I don't think that's going to work out the way you hope. Something is going to have to give, and I suggest that the best point for that is server-side. Drink the knockout cool-aid and fix what you have to server-side.

Categories