1

I am trying to use a custom validation but its been ignored. I do not get any errors or anything. It simply does nothing. What am i doing wrong? Thank you for reading.

---ModelMetadata.cs----

using System.ComponentModel.DataAnnotations; 
using myproject.Common;

namespace myproject.Models
{
    [MetadataType(typeof(ModelMetaData))]
    public partial class Reference
    { 
    }

    public class ModelMetaData { 
        [Required]
        [Display(Name = "Full Name *")]
        [ExcludeCharacters("/.,!@#$%")] // <<<====== This is being ignored. 
        public string Name { get; set; } 
    }
}

--Create.cshtml ----

<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script> 
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

@using (Html.BeginForm()){
@Html.AntiForgeryToken()
@Html.ValidationSummary(true) 

    <div class="editor-field">
        @Html.EditorFor(model => model.Name) // <<<====== field 
        @Html.ValidationMessageFor(model => model.Name)
    </div>

--ExcludeCharacters.cs ---

namespace myproject.Common
{
    public class ExcludeCharacters : ValidationAttribute 
    {
        private readonly string _chars;

        public ExcludeCharacters(string chars) : base("{0} contains invalid characters")
        {
            _chars = chars;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                for (int i = 0; i < _chars.Length; i++)
                {
                    var valueAsString = value.ToString();
                    if (valueAsString.Contains(_chars[i].ToString()))
                    {
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    }
                }
            }
            return ValidationResult.Success;  
        }  
    } 
}
4
  • Have you debugged your validation attribute? Have you considered instead, using a regular expression to prevent certain characters from being entered? Commented Oct 30, 2014 at 16:03
  • sorry. when i run the program i get this error: "Unable to get value of the property 'unobtrusive': object is null or undefined". I googled around and tried few suggestions but no luck. Commented Oct 30, 2014 at 16:38
  • Whereabouts does this error occur? Commented Oct 30, 2014 at 16:41
  • Actually I restarted VS and error went away but its still not working. There are no errors or anything being generated when debugging. I could try doing doing regular expressions but I just wanted to learn more about custom validation. Commented Oct 30, 2014 at 16:59

3 Answers 3

1

Please check the action method in your controller - make sure the model type is used by a parameter, e.g.

public ActionResult Foo(ModelMetaData model)
Sign up to request clarification or add additional context in comments.

Comments

0

i had exactly same problem, and was using same codes as well. i simply shutdown my application and restarted again. it worked for me. try this

1 Comment

in the comments, it looks like the original asker tried this already.
0

Your code generally looks about right. This would validate, however, at the server side, the way you generally have it and if it was working. Moreover, I'm unsure of why some examples are only overriding the ValidationResult version of the IsValid method, and yet other examples are only overriding the bool variant.

If you want client side validation, you need to implement IClientValidatable , and register the adapter on the client side.

Below is some code I was able to make work. I needed to include my js file after my validation inclusion, and since I was using DevExpress with include client libraries, I needed to run it after them as well.

You'll also (for client side to work), want to use EditorFor or TextBoxFor type methods to add the fields, but this appears to be something you are already doing. Do, however, check your html and look for said validation proprieties being added.

I've tested this with my MM/dd/yyyy fields.

RangeSmallDateTime.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace YourNamespaceHere.Filters
{
    public class RangeSmallDateTime : ValidationAttribute, IClientValidatable
    {
        private static DateTime _minValue = new DateTime(1900, 1, 1);
        private static DateTime _maxValue = new DateTime(2079, 6, 6);

        public override bool IsValid(object value)
        {
            DateTime? dateValue = value as DateTime?;

            if (!dateValue.HasValue)
            {
                return true;
            }
            else 
            {
                return (dateValue.Value >= _minValue && dateValue.Value <= _maxValue);
            }
        }

        public override string FormatErrorMessage(string name)
        {
            return string.Format("The '{0}' field has an invalid value.", name);
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "rangesdt";
            yield return rule;
        }


    }
}

SmallDateTimeValidator.js:

$.validator.unobtrusive.adapters.addBool("rangesdt");

$.validator.addMethod("rangesdt", function (value, element) {
    if (value == null) {
        return true;
    }
    var date = new Date(value);  // MM/dd/yyyy

    var minDate = new Date(1900,1,1);
    var maxDate = new Date(2079, 6, 6);

    if (!dates.inRange(date, minDate, maxDate))
        return false;

    return true;
});

// Source: http://stackoverflow.com/questions/497790
var dates = {
    convert: function (d) {
        // Converts the date in d to a date-object. The input can be:
        //   a date object: returned without modification
        //  an array      : Interpreted as [year,month,day]. NOTE: month is 0-11.
        //   a number     : Interpreted as number of milliseconds
        //                  since 1 Jan 1970 (a timestamp) 
        //   a string     : Any format supported by the javascript engine, like
        //                  "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
        //  an object     : Interpreted as an object with year, month and date
        //                  attributes.  **NOTE** month is 0-11.
        return (
            d.constructor === Date ? d :
            d.constructor === Array ? new Date(d[0], d[1], d[2]) :
            d.constructor === Number ? new Date(d) :
            d.constructor === String ? new Date(d) :
            typeof d === "object" ? new Date(d.year, d.month, d.date) :
            NaN
        );
    },
    compare: function (a, b) {
        // Compare two dates (could be of any type supported by the convert
        // function above) and returns:
        //  -1 : if a < b
        //   0 : if a = b
        //   1 : if a > b
        // NaN : if a or b is an illegal date
        // NOTE: The code inside isFinite does an assignment (=).
        return (
            isFinite(a = this.convert(a).valueOf()) &&
            isFinite(b = this.convert(b).valueOf()) ?
            (a > b) - (a < b) :
            NaN
        );
    },
    inRange: function (d, start, end) {
        // Checks if date in d is between dates in start and end.
        // Returns a boolean or NaN:
        //    true  : if d is between start and end (inclusive)
        //    false : if d is before start or after end
        //    NaN   : if one or more of the dates is illegal.
        // NOTE: The code inside isFinite does an assignment (=).
        return (
             isFinite(d = this.convert(d).valueOf()) &&
             isFinite(start = this.convert(start).valueOf()) &&
             isFinite(end = this.convert(end).valueOf()) ?
             start <= d && d <= end :
             NaN
         );
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.