Why MVC Model Binder set required for int, long values? - asp.net-mvc

I have a Model Like this
public int Id {get;set;}
[Required]
public string FirstName{get; set}
[Required]
public string LastName{get; set}
The Id is auto generate in DB. when I want call Create action The ModelState says that "The Id field is required"!!!! I Found this for my problem but it not clean solution.
Is there an other way to solve this?
Is there a way that I change Mvc ModelBinder behavior for value types?

The best solution to this problem is to use a view model. A view model is a class that you specifically design to meet the requirements of your view. So your controller action will take this view model as parameter. Simply stop passing your domain models to your views. That's it.
And if you don't want to follow good practices and use view models you could disable this implicit validation by adding the following to your Application_Start:
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
another hack is to exclude this property from binding using the [Bind(Exclude = "Id")] attribute. Yeah, it's a hack but if you don't follow good practices you will have to live with hacks.

Although #DarinDimitrov suggested a good option to use View Models, In addition to that answer. Also, consider this option only when you don't want to create the View-Model
How about ModelState["Id"].Errors.Clear(); in your Post Action Method ?

You can also set the property type to Nullable<T>, and then just manually enforce any required validation you might need to do before working with the database.
public int? Id {get;set;}
Further Reading:
Unrequired property keeps getting data-val-required attribute
ASP.NET MVC optional field being treated as required
"The Id field is required" validation message on Create

Related

ModelState: Validate only the properties that are inside the form

I have a User class with multiple string properties, all of them required. The properties are used for different actions, like Create and Update.
In my form, on create action, i am using only a part of these properties, and, because of this, the ModelState is invalid.
Is there a way to specify to the ModelState that it should validate only the properties that are included in the POST data (inside the form) ? So the missing properties are ignored?
You can create different models for user creation and other actions with different sets of validation attributes.
Yea, you should create different view models for each specific action method ( if they have specific requirements ).
You can use the RequiredIf attribute from Foolproof to achieve this:
using Foolproof;
[RequiredIf("Tab", "Information")]
public bool UW_AgentCreditReportsAknowlegement { get; set; }
Just use one of the attributes and set the appropriate condition.

How to establish validation dependency between two viewmodels?

I swear to god, that I had seen something like (below) on one of the MSDN Article but I cant find this property attribute documentation anywhere.
public class MyViewModel{
[Required]
public bool Important {get;set;}
[ValidationDependsOn("Important")]
public bool HasVIPAccess {get;set;}
}
If you look at the above code (maybe a bad example), I am trying to establish a relationship between the two properties in such a way that validation of HasVIPAccess property depends on the validation of the property called Important.
the built in validation attribute that do something like that is [Compare("OtherProperty")] which means the property that you put this attribute on must equal OtherProperty
ex
public class MyViewModel{
[Required]
public bool Important {get;set;}
[Compare("Important")]
public bool HasVIPAccess {get;set;}
}
Note : Require MVC 3+
if you wanna other validation attributes you can check Mvc.ValidationTookit
if you want to understand the science behind it
this is new to mvc3 and you can implement your custom attribute like this fairly easy in mvc3
because IsValid now recives a ValidationContext parameter which contains information about the validation that is being performed like the type of the model and metadata associated with it so you can use reflection to get other properties and their value the CompareAttribute made use of this feature
FluentValidation.NET
You can do this by writing a custom validation attribute (this enables only server side validation)... Here is a relevant post Creating New Data Annotation Validation Attributes in MVC
However...if you want to get client side unobstrusive validation to work as well, then you need to do some javascript work...here is another post that talks about creating unobtrusive client side validation...Unobtrusive Client Validation with MVC 3

How to avoid needing a VIewModel for every Model

I'm using ASP.NET 4 and MVC3.
Often, I find that I need a ViewModel to display information for my Model. For example, take the following model
class Profile
{
public int UserID { get; set; }
public string Name { get; set; }
public DateTime DOB { get; set; }
}
There is a requirement to hide the UserID, but to show the UserName, so often time for models that are similar to the one above, I have to come up with a ViewModel with just the UserID changed to UserName:
class ProfileViewModel
{
public string UserName { get; set; }
public string Name { get; set; }
public DateTime DOB { get; set; }
}
Are there any ways?
Until recently I always passed my models to my action methods as I also thought that creating viewModels with the same property names was duplication (its not). This caused me a lot of pain. I have now been re-educated and almost always use viewModels exclusively in my action methods (of course there will always be situations were it is fine to pass the model directly to the action method).
Have a read of this post which is the one that converted me to using viewModels. This will tell you the following:
The difference between models and viewModels
When each should be used.
How to avoid some security issues with the default model binder.
On top of the information in the linked post you should also consider things such as validation. I had a model that implemented the IValidateableObject interface to ensure the entity was in a valid state before being saved to the database.
In my ASP.NET application I wanted to create a multi-step form that allowed the user to enter the information over a number of pages. The problem I had here was that ASP.NET also uses the IValidatableObject interface during the model binding process.
If you are only allowing the user to enter a subset of the information required for the entity, the model binder will only be able to fill in the information that was given. Depending on how complex your validation is, this can result in the ModelState being marked as invalid as the entire entity is not valid.
The way I got around this was to have a viewModel representing each step each with its own validation. This way you are only validating the properties at each step. Once you get to the final step and everything is valid, I create an appropriate entity using the information given by the user. This entity will only have database-level validation checks performed upon it (field lengths etc.)
My suggestion is not to avoid viewModels but to understand why they are used and embrace them.
No, there isn't, once a member is public, it's public. Now, if the UserID property was internal, then you wouldn't have that problem.
However, one of the aims of MVVM here is to encapsulate logic regarding the interaction of the model and the view. Even if you have the view model and model in separate assemblies and make the UserID property internal, you should still have a view model; if changes come down the line where more functionality is required than simply binding to the model, you are prepared.
Direct access to the model is always a no no.
Additionally, if you really wanted, you could always use T4 templates to auto-generate the code for you (you could use Code DOM on the original CS file) to output your view models for you.
I usually have multiple ViewModels per model - the tradeoff you have to make comes down to this:
Are you comfortable coupling business logic (data annotations, display information, etc...) with your (persistence) models?
Are you comfortable doing all of the hide / display business logic purely within the View and not use the Controller + scaffolding to make those decisions for you?
The downside of creating all of those ViewModels of course is sub-class explosion, but the right way to think about it is in terms of the questions I listed IMHO.

Make a required class properties not required

I have a class set up to hold values on a registration form (VB.NET, MVC), and among the properties is a Password property:
Public Class RegisterModel
...
Private _password As String
<DisplayName("Password:"), Required(), ValidatePasswordLength(), DataType(DataType.Password)> _
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal value As String)
_password = value
End Set
End Property
This works great when registering a new user, but I'd like to use the same class to update existing users. (Note: this app is run by an admin who is in charge of registering individuals and assigning passwords.) The way I'd like it to behave is if the admin leaves the password blank, then the password is not changed, but the rest of the information is. If I use this class, the password can't be left blank because it fails on the Required() and ValidatePasswordLength() calls.
Is there a way to use this class but tell the model to ignore these particular validations? Even if I leave the password field off my edit form, it still fails. Do I need to create a whole duplicate class without these restrictions on the password field? There must be a better way.
You could implement IDataErrorInfo and have a flag set on the model which indicates whether it is being used by an admin or not - you could then validate conditionally.
But overall, I'd say this is a bit of a code smell. You're using a model for two different, incompatible purposes. It'd be better to use a separate view model.
I'd recommend using the FluentValidation library. It's a fantastic way to separate the concerns of your view (view model) and the actual validation you want to perform. You could pass parameters into it to drive different behavior. Check out When/Unless conditions or just writing completely custom validation methods with the Must operator.
public class RegisterModelValidator: AbstractValidator<RegisterModel>
{
public RegisterModelValidator(bool isAdmin)
{
RuleFor(x => x.Password).NotEmpty().Unless(isAdmin);
...
}
}
As long as your view model would have identical properties in both scenarios, you should use the one view model and one validation class. If the model varies at all I'd use two view models as David recommends.
You can do this in 2 ways:
1: add the [ValidateInput(false )] attribute to the action
or
2: Add a new property to the Register Model
public bool IsNewUser {get;}
3: Create a new class level attribute that takes IsNewUser into account when validating

How can I use a custom ValidationAttribute to ensure two properties match?

We're using xVal and the standard DataAnnotationsValidationRunner described here to collect validation errors from our domain objects and view models in ASP.NET MVC. I'd like to have a way to have that validation runner identify when two properties don't match through the use of custom DataAnnotations.
Right now I'm forced into doing it outside of the runner, this way:
if (!(model.FieldOne == model.FieldTwo))
errors.Add(new ErrorInfo("FieldTwo", "FieldOne must match FieldTwo", model.FieldTwo));
My question is: can this be done using property-level validation attributes, or am I forced into using class-level attributes (in which case, I'd have to modify the runner...and my follow up question would be how best to retrieve them in that case).
Thanks!
UPDATE: I finally figured out how to write the object query to implement the suggestion in the selected answer; I concat the results of this query with the results of the standard validation runner, if anyone was curious. Note that I changed the TypeId to be the confirm field property.
var classErrorQuery =
from attribute in
instance.GetType().GetCustomAttributes(typeof (ValidationAttribute), false).Cast
<ValidationAttribute>()
where !attribute.IsValid(instance)
select new ErrorInfo(attribute.TypeId.ToString(), attribute.FormatErrorMessage(string.Empty), instance);
see Writing a CompareTo DataAnnotation Attribute
and also you can check The AccountMOdel in the default project of MVC2, There is an attribute PropertiesMustMatchAttribute applied to the ChangePasswordModel to validate that the NewPassword and ConfirmPassword Match

Resources