Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize the Error Message MVC for an invalid DateTime in ASP.NET MVC4

I am having trouble specifying the error message for the validation of a DateTime input value using data annotations in my model. I would really like to use the proper DateTime validator (as opposed to Regex, etc).

[DataType(DataType.DateTime, ErrorMessage = "A valid Date or Date and Time must be entered eg. January 1, 2014 12:00AM")]
public DateTime Date { get; set; }

I still get the default date validation message of "The field Date must be a date."

Am I missing something?

like image 244
Chris Albrecht Avatar asked Mar 13 '13 04:03

Chris Albrecht


4 Answers

Add the following keys into Application_Start() at Global.asax

ClientDataTypeModelValidatorProvider.ResourceClassKey = "YourResourceName";
DefaultModelBinder.ResourceClassKey = "YourResourceName";

Create YourResourceName.resx inside App_GlobalResources folder and add the following keys

  • FieldMustBeDate The field {0} must be a date.
  • FieldMustBeNumeric The field {0} must be a number.
  • PropertyValueInvalid The value '{0}' is not valid for {1}.
  • PropertyValueRequired A value is required.
like image 66
cilerler Avatar answered Oct 07 '22 14:10

cilerler


I found one simple workaround.

You can leave your model untouched.

[DataType(DataType.Date)]
public DateTime Date { get; set; }

Then override the 'data-val-date' attribute in a view.

@Html.TextBoxFor(model => model.Date, new
{
    @class = "form-control",
    data_val_date = "Custom error message."
})

Or if you want to parameterize your messages, you can just use static function String.Format:

@Html.TextBoxFor(model => model.Date, new
{
    @class = "form-control",
    data_val_date = String.Format("The field '{0}' must be a valid date.",  
                                    Html.DisplayNameFor(model => model.Date))
})

Similar with resources:

@Html.TextBoxFor(model => model.Date, new
{
    @class = "form-control",
    data_val_date = String.Format(Resources.ErrorMessages.Date,  
                                   Html.DisplayNameFor(model => model.Date))
})
like image 37
Pavol Korvas Avatar answered Oct 07 '22 13:10

Pavol Korvas


I have one dirty solution.

Create custom model binder:

public class CustomModelBinder<T> : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if(value != null && !String.IsNullOrEmpty(value.AttemptedValue))
        {
            T temp = default(T);
            try
            {
                temp = ( T )TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(value.AttemptedValue);
            }
            catch
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName, "A valid Date or Date and Time must be entered eg. January 1, 2014 12:00AM");
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
            }

            return temp;
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

And then in Global.asax.cs:

protected void Application_Start()
{
    //...
    ModelBinders.Binders.Add(typeof(DateTime), new CustomModelBinder<DateTime>());
like image 42
x2. Avatar answered Oct 07 '22 14:10

x2.


I got around this issue by modifying the error in the ModelState collection at the start of my action method. Something like this:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult MyAction(MyModel model)
    {
        ModelState myFieldState = ModelState["MyField"];
        DateTime value;
        if (!DateTime.TryParse(myFieldState.Value.AttemptedValue, out value))
        {
            myFieldState.Errors.Clear();
            myFieldState.Errors.Add("My custom error message");
        }

        if (ModelState.IsValid)
        {
            // Do stuff
        }
        else
        {
            return View(model);
        }
    }
like image 25
Martin Brown Avatar answered Oct 07 '22 14:10

Martin Brown