1

I have a Date field , and I would like to verify that this date is higher than today's date.

<script>
    jQuery.validator.addMethod("currentdate", function (value, element) {
        return Date.parse(value) > Date.parse(new Date());
    }, jQuery.validator.format("Date invalid"));
</script>

    @Html.LabelFor(m=>m.booking.Date)
    @Html.TextBoxFor(m => m.booking.Date, new { @class = "form-control", @id="Date" })
    @Html.ValidationMessageFor(m=>m.booking.Date)

What is the approach to take ? How do I have to structure my html helper ?

Luke
  • 22,826
  • 31
  • 110
  • 193
Matthieu Veron
  • 290
  • 6
  • 16
  • What is the problem that you have? – Luke Jul 03 '17 at 09:19
  • I don't know how to do this validation. At the moment, I just add the method to the validator. – Matthieu Veron Jul 03 '17 at 09:25
  • ASP.NET MVC uses unobtrusive validation, so applying your method to `jQuery.validator` isn't going to work. You need to use the `$.validator.unobtrusive.adapters.add` method and other parts of the `unobtrusive` JavaScript library. Please check out this URL https://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2 for a decent low down on how to implement a custom client validation attribute. – Luke Jul 03 '17 at 09:33
  • It not really helps me. I don't need a validation which uses others propriety. I want a simple validation which verify if the date is higher than the today's date – Matthieu Veron Jul 03 '17 at 10:42
  • Sadly there isn't built in support for validating a date range, you can either do it on the client side using a custom validation attribute or just do it on the server side as part of the validation performed when the controller action has been executed. General information about validation in asp.net mvc can be found at the following URL https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation – Luke Jul 03 '17 at 11:29
  • I already did it server-side with a custom data annotation, now i want to do it client-side using a custom validation attribute. It was the point of my question. How can I do the client-side validation using the custom validation attributes ? – Matthieu Veron Jul 03 '17 at 12:16
  • Ok, well have a look at that article that I mentioned. How does it 'not really help'? It explains how to implement server side and client side validation for unobtrusive validation for a custom attribute....................... – Luke Jul 03 '17 at 12:59
  • Look at the first example in the part : "Creating a custom jQuery validate function" There is a validator.addMethod(...) like I did in my code. But you said it isnt going to work and that i have to use validator.unobtrusive.adapters.add. And on the example : $.validator.unobtrusive.adapters.addSingleVal("notequalto", "otherproperty"); It uses "otherproperty", because it's a validation which compares 2 fields in the form. But in my case, the validation is only about one field, so I dont need "otherproperty", so I dont understand the role of this line. I would just like a simple example. – Matthieu Veron Jul 03 '17 at 13:17
  • Moreover, it does not explain how to have the right attributes using the helpers. In fact, I would especially like to have the process to follow. That is, what am I supposed to do to get the result I want. From what I understood I have to write the jQuery part, (with the validator.adddMethod and the validator.unobtrusive.adapters ?), and then put the right attributes in the html code. That's all ? – Matthieu Veron Jul 03 '17 at 13:19
  • I have just taken some time to get this working, I've posted it as answer. I hope that it helps :). – Luke Jul 03 '17 at 15:01
  • 1
    It really helps ! Thank you !! – Matthieu Veron Jul 03 '17 at 15:27
  • It's not perfect, it'll probably need tweaking to handle invalid entries but hopefully it will get you going with it. You were right about the `$.validator.addMethod` bit, but we got there in the end – Luke Jul 03 '17 at 15:46

1 Answers1

0

Assuming the following form with a text box called Date:

@model TestFormViewModel

@{
    ViewBag.Title = "Index";
    HtmlHelper.ClientValidationEnabled = true;
    HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
}

<h2>Test Form</h2>

@using (Html.BeginForm())
{
    @Html.TextBoxFor(x => x.Date)
    @Html.ValidationMessageFor(x => x.Date)
    <input type="submit" value="Submit" />
}

@section scripts {  
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate-vsdoc.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
    <script src="~/Scripts/validationrule.js"></script>
}

Simple controller action:

[HttpPost]
public ActionResult Index(TestFormViewModel requestResponsemodel)
{
    return View(requestResponsemodel);
}

A JavaScript file included into the page called validationrule.js:

$.validator.unobtrusive.adapters.add("currentdate", [], function (options) {
    options.rules['currentdate'] = options.params;
    if (options.message) {
        options.messages['currentdate'] = options.message;
    }
});

$.validator.addMethod("currentdate",
    function (value, element, other) {

        return Date.parse(value) > Date.parse(new Date());
    }
);

DateValidationAttribute.cs containing your server side validation:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class CurrentDateValidationAttribute : ValidationAttribute, IClientValidatable
{

    // Default error message, can be overridden in the use of the attribute on your model
    public CurrentDateValidationAttribute() : base("The date must be later than the current date.")
    {
    }

    public override bool IsValid(object value)
    {
        var dateToValidate = (DateTime)value;
        return dateToValidate > DateTime.UtcNow;
    }

    // Client-Side validation 
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientCurrentDateValidationRule("The date must be later than the current date.");
        yield return rule;
    }
}

... and a ModelClientValidationRule that will put the error message into the output of your Html helper (@Html.TextBoxFor()) to be picked up on the client side by your JavaScript validation code:

public class ModelClientCurrentDateValidationRule : ModelClientValidationRule
{
    public ModelClientCurrentDateValidationRule(string errorMessage)
    {
        ErrorMessage = errorMessage;
        ValidationType = "currentdate";
    }
}

The model to validate with the custom validation attribute assigned to your model, in this case the Date property:

public class TestFormViewModel
{
    [CurrentDateValidation(ErrorMessage = "The date must be later than the current date.")]
    public DateTime Date { get; set; }
}

Your date field will validate on the client site as invalid when the date contained in the field is before the current date, like so:

validation for field before the current date

Luke
  • 22,826
  • 31
  • 110
  • 193