suryakiran
suryakiran

Reputation: 1996

Data type client side validation not working in MVC 2

We have an attribute called DateReleased for which the following Data Annotation attributes are added

[Required]
[DataType(DataType.Date, ErrorMessage = "Please enter date")]
[DisplayName("Date Released")]
public object DateReleased { get; set; }

Following is the Action which is implemented to insert a new record to the database

[HttpPost]
public ActionResult Create([Bind(Exclude="Id")] Movie movie)
{
    try
    {
        if (ModelState.IsValid)
        {
            _entities.AddToMovies(movie);
            _entities.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(movie);
    }
    catch
    {
        return View();
    }
}

I have enabled the client validation, by placing the following lines of code in the create view

<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="../../Scripts/jquery.validate.js"></script>
<script type="text/javascript" src="../../Scripts/MicrosoftAjax.js"></script>
<script type="text/javascript" src="../../Scripts/MicrosoftMvcAjax.js"></script>
<script type="text/javascript" src="../../Scripts/MicrosoftMvcValidation.js"></script>

<% Html.EnableClientValidation(); %>

But I was surprised to find that only Required validation is firing on client side. Data Type validation of Date is only firing at server side. Please let me know the reason behind the failure of client side validation and what would be workarounds to fire the client side validation.

Upvotes: 2

Views: 1473

Answers (2)

Nath
Nath

Reputation: 56

Yes. Add a custom attribute class as below

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DateAttribute : DataTypeAttribute
{
    public DateAttribute() : base(DataType.Date) { }

    public override string FormatErrorMessage(string name)
    {
        if (ErrorMessage == null && ErrorMessageResourceName == null)
        {
            ErrorMessage = ValidatorResources.DateAttribute_Invalid;
        }
        return base.FormatErrorMessage(name);
    }

    public override bool IsValid(object value)
    {
        if (value == null) return true;
        DateTime retDate;
        return DateTime.TryParse(Convert.ToString(value), out retDate);
    }
}

Create Client Validation Rule class

public class ModelClientValidationDateRule:ModelClientValidationRule
{
    public ModelClientValidationDateRule(string errorMessage)
    {
        ErrorMessage = errorMessage;
        ValidationType = "date";
    }
}

Create an adapter class which hooks in the custom attribute and client validation rule as below. Make sure of adding refernce of the above attribute class

public class DateAttributeAdapter : DataAnnotationsModelValidator<DateAttribute>
{
    public DateAttributeAdapter(ModelMetadata metadata, ControllerContext context, DateAttribute attribute)
        : base(metadata, context, attribute) { }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        return new[] { new ModelClientValidationDateRule(ErrorMessage) };
    }
}

Then modify the global.asax file

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterRoutes(RouteTable.Routes);

    DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(DateAttribute), typeof(DateAttributeAdapter));
}

Adding the Attribute to the model class as below

[Date]
public object DateReleased { get; set; }

Adding following client side code in the view

<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="../../Scripts/jquery.validate.js"></script>
<script type="text/javascript" src="../../Scripts/MicrosoftAjax.js"></script>
<script type="text/javascript" src="../../Scripts/MicrosoftMvcAjax.js"></script>
<script type="text/javascript" src="../../Scripts/MicrosoftMvcValidation.js"></script>
<script type="text/javascript">

Sys.Mvc.ValidatorRegistry.validators["date"] = function (rule) {
    // initialization code can go here.
    return function (value, context) {
        if (value.length > 0) {
            var d = new Date(value);
            if (!isNaN(d))
                return true;
            return rule.ErrorMessage;
        }
        else {
            return true;
        }
    };
};

Hope this would help you.

Upvotes: 4

Erik Funkenbusch
Erik Funkenbusch

Reputation: 93494

The DataTypeAttribute does not do validation. It's really only used for selection of Editor/DisplayTemplates (and thus controls how data is formatted), and also for formatting selection within generic templates.

I'm not sure why you thought this did any kind of validation, but it doesn't. What does control validation is the actual data type. Since you created your data item as object, it can't do any vlidation of date format. Instead, make your properties type DateTime? or Nullable

Upvotes: 3

Related Questions