tags:

views:

1799

answers:

6

I am checking a datetime field in mvc view for datetime format like this:

        If contactToValidate.LastUpdated = Nothing OrElse Not IsDate(contactToValidate.LastUpdated) OrElse CType(contactToValidate.LastUpdated, DateTime) = DateTime.MinValue Then
             _validationDictionary.AddError("AddErrorValue", "Date Format is not Correct!")
        End If

but , if the input for LastUpdated in View , left blank, beside my own error ("Date Format is not Correct!") , the default error message is shown: A value is required. I believe this is what mvc framework automatically checked for datatype conversions, but as I'm checking the LastUpdated textbox for null and datetime format, I dont want this error message to be shown. I just want my own. How can I do that? Thanks

+3  A: 

You are probably getting this message because the date field is being bound to a non-nullable DateTime on your presentation model. If you change the type of that field or property to a nullable DateTime, you should no longer get this message.

In any event, you can customize the message that the user sees by implementing IDataErrorInfo on your presentation model.

Craig Stuntz
thats true, but I want it to be non-nullable..
mohamadreza
I gave you instructions for that, right? Implement IDataErrorInfo.
Craig Stuntz
as you can see at the end of that article: "If you want to modify the error message for the DateReleased property then you need to create a custom model binder." so with default model binder , there is noway to override that err-msg while checking for not null DateTime fields.I think its weird!
mohamadreza
I think it's a bug - if not, it's annoying as hell. I tried implementing validation code based on the article Craig mentioned, implemented a partial class that implemented IDataErrorInfo, adding the appropriate partial void methods, but my validation code for the non-null field (an int in my case) was never called.
chris
A: 

I belive what you're looking for is this

ViewData.ModelState.AddModelError("FieldName", "Date Format is not Correct!");

This will force <%=Html.ValidationMessage("FieldName") %> to show your error message.

Edit : I just checked and this will not actually solve the problem. You should refer to Craig Stuntz's answer about non-nullable type and IDataErrorInfo and then you can add your own error message for the empty field.

çağdaş
It seems there is always problem with Not-Null DateTime inputs, the default binder, add this "A value is required" statement beside every other error messages you add manually to modelstate.
mohamadreza
+2  A: 

I tried implmenting IDataErrorInfo on my partial classes but I still got the rogue 'A value is required' error message for dropdownlists that haven't had anything selected in them ie return null rather than an integer for a foreign key.

I've taken to doing this on the first line of my Create action:

       public ActionResult Create([Bind(Exclude="Id")]MyEntity myEntityToCreate)
    {
        foreach (string key in ModelState.Keys){
            ModelState[key].Errors.Clear();
        }

and then rely on my custom model validation code that fires when the object is saved to add meaningful error messages to the ModelState collection when dropdown items not selected.

It's probably not the best way to do it.

+2  A: 

I ran into this issue too - it does indeed seem to occur where a model field is bound to a non-nullable type on your data model.

The way I've bypassed this is to clear down the error information in the ModelState. In my exception handler on my controller method, I do this:

foreach (var state in ModelState.Values)
{
  if (state.Errors.Count > 0) 
    state.Errors.Clear();
}

which removes the default validation behaviour, then runs my own. Note that doing this will leave you with errors but no description if your own validation doesn't cover all of your fields. If it is only a single field that you want to clear however, you can check for its name in the ModelState dictionary, and just clear that one.

Jon Artus
it will solve the problem but it should not be the significant way. didn't try it on mvc2.0 yet. but no idea if it is a bug in mvc1.0 or it has a solid solution which I couldn't find anywhere!
mohamadreza
Yeah, I couldn't find a good solution either - it feels like there should be a better way! I'll keep an eye out in V2.0 anyway.
Jon Artus
+2  A: 

It's unfortunate that no matter where you look, most of the answers to this question are "Implement IDataErrorInfo!".

This same problem shows up if you try to, for example, type a text string into a textbox field bound to an integer property. Simply, if MVC cannot convert the user value to the proper type, it generages these (quite useless) generic errors and never calls upon the IDataErrorInfo members.

It's definately a hassle to override these unhelpful messages, and personally I feel the best answer is to simply implement some client-side validation to handle these scenarios. The cases where it generates these messages are very consistent and easily predictable:

  • The user hasnt supplied a value for a non nullable field
  • The user has entered or selected a value which isnt convertable to the underlying type (for exmaple: text into a numeric field)

Plus, client side validation is just good practice anyways. If the user doesnt have javascript enabled then they'll certainly be able to figure out the problem anyways if you're using Html.ValidationMessage() and / or styling the input fields to identify the problems.

Shaun Rowan
A: 

If you want to exclude a property from validation, then the best way to do it if you are using the model binding then you want:

public ActionResult Create([Bind(Exclude="LastUpdated")] Contact contactToValidate)
{

}

if on the other hand you are using UpdateModel or TryUpdateModel, you can use:

string prefix = string.Empty;
string[] includedProperties = new string[0];
string[] excludedProperties = new [] { "LastUpdated" };

TryUpdateModel<Contact>(contactToValidate, prefix, includedProperties, excludedProperties);

Note that since you are sending in an empty array for the included properties, you are in fact including ALL properties, and the one excluded property is then taken from this set.

Tahir Hassan