ASP.NET MVC 4 - Clientside Validation Not Working
Asked Answered
S

1

10

I am using Visual Studio 2012 and I cannot get a custom attribute client side logic to work to reproduce at a smaller scale, I created a new MVC 4 project I created the following model and Attribute that will never validate

public class MyModel
{
    public int Id { get; set; }
    [Required]
    public string LastName { get; set; }
    [NeverValid(ErrorMessage="Serverside Will Never Validate")]
    public string FirstName { get; set; }
}

public class NeverValidAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return false;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
    }

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

I then have the following actions added to the HomeController

public ActionResult Index()
{
    return View(new MyModel());
}

[HttpPost]
public ActionResult Index(MyModel model)
{
    if (!ModelState.IsValid)
    {
        // Will Always Be Invalid
    }

    return View(model);
}

There is also a javascript file called nevervalid.js

$(function () {
    $.validator.addMethod("nevervalid", function () {
        return false;
    }, "Clientside Should Not Postback");

    $.validator.unobtrusive.adapters.addBool("nevervalid");
});

and the Index View

@model CustomAttribute.Models.MyModel

@{
    ViewBag.Title = "Home Page";
}

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

    <fieldset>
        <legend>MyModel</legend>

        @Html.HiddenFor(model => model.Id)

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

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

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/Scripts/nevervalid.js")
}

The relevant areas in my web.config look like this

<appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

when the page loads, the following files are loaded (got this from network tab under chrome's F12)

http://localhost:7440/
http://localhost:7440/Content/site.css
http://localhost:7440/Scripts/modernizr-2.5.3.js
http://localhost:7440/Scripts/jquery-1.7.1.js
http://localhost:7440/Scripts/jquery.unobtrusive-ajax.js
http://localhost:7440/Scripts/jquery.validate.js
http://localhost:7440/Scripts/jquery.validate.unobtrusive.js
http://localhost:7440/Scripts/nevervalid.js

and my custom attribute adds relevant looking data- stuff to the first name input like so...

    <input class="text-box single-line valid" data-val="true" data-val-nevervalid="Serverside Will Never Validate" id="FirstName" name="FirstName" type="text" value="">

so, I ask you, why oh why does this thing have to postback to do serverside validation while I have some perfectly looking javascript code here? do I have to sacrifice some animal on a moonless night on top of a hill somewhere?

Starveling answered 20/3, 2013 at 16:41 Comment(2)
Does this help, it seems you're not overriding all the required functions in your validation attribute. #8284707Inquisitionist
Hi, Patrick, thanks for taking your time to look at the problem, In my rush to get the smallest reproducable code, I overlooked the second IsValid override... still it does not work... I think I must've gone through all the related SO questions. but nothing... I'm hoping that someone may be able to reproduce it on their end of the world, confirm I aint going insane...Starveling
I
19

I'm wondering what would happen if you altered nevervalid.js so that the code executes before the document is ready.

My basic thinking is that the unobtrusive validation works by parsing the document when the dom is ready... but if you're loading your custom validation stuff at the same time / afterwards, it's not going to know what to do when it comes accross you custom validation data- attribute.

Anyway, try changing nevervalid.js to simply be:

(function($) {
    $.validator.addMethod("nevervalid", function () {
        return false;
    }, "Clientside Should Not Postback");

    $.validator.unobtrusive.adapters.addBool("nevervalid");
})(jQuery);
Ives answered 20/3, 2013 at 17:58 Comment(6)
yea, still works and the edit does look much more less "naked", been using jQuery for too long and there are some stuff in it I forgot to ask what they actually mean...Starveling
All good, glad it fixed you problem. The edit was just a best practice thing :-)Ives
Can anyone help me what is difference between (function($){})(jQuery) and $(document).ready(function{})??Denishadenison
$(document).ready(function{}) gets called when the document is ready (everything has loaded dome is ready blah blah...) (function($){})(jQuery) will be fired immediately it is encountered, it is basically just function($){} called immediately with jQuery as the parameter... hope it makes senseStarveling
Thanks a lot @Ives after many struggle your answer is very useful to me. I wish I can give you more votes for your answer.Sesterce
Thanks for that, that's very helpful, I didn't pay much attention on that subtle part. However, this subtle part change the whole picture. :-)Nkrumah

© 2022 - 2024 — McMap. All rights reserved.