30

Running Visual Studio 2013, I created a new ASP.NET MVC (5) project, with Bootstrap.

However, I'm unable to get unobtrusive client-side validation working.

The model has [Required] attributes on the relevant properties and the view has ValidationMessageFor... tags for each field in the form.

However, submitting the form causes the form to postback to server before validation messages appear.

Using NuGet, I've installed jquery.validate and jquery.validate.unobtrusive and added them to the jquery bundle in App_Start.

Yet it continues to stubbornly post back to server. F12 dev tools shows no JS errors/warnings.

Has anybody else come across this issue (can't see anything in SO relating to MVC 5 specifically) and do you have any ideas?

SharpC
  • 6,974
  • 4
  • 45
  • 40
SimonGoldstone
  • 5,096
  • 3
  • 27
  • 38
  • Can you check the html that its generating if it has the `data-val` and other validation attributes? – WannaCSharp Nov 02 '13 at 02:21
  • @WannaCSharp Thanks. Yes, the data-val attributes are all there as expected – SimonGoldstone Nov 02 '13 at 22:27
  • Does it work when you remove the Bootstrap JavaScript? – jHilscher Nov 03 '13 at 16:26
  • @jHilscher Thanks. No, unfortunately it doesn't. – SimonGoldstone Nov 04 '13 at 00:07
  • 1
    I've just created a new MVC app from the start and validation works without any issue. I cannot for the life of me find a rational reason why the first app doesn't work. I've starting copying the code and views over one by one, so if it stops working I can pinpoint the reason. Other than that, totally out of ideas. – SimonGoldstone Nov 04 '13 at 00:08
  • 1
    Further to my last message, I've now migrated all the code and views over to the 'new' application and it all works. Frustrating - never got to the bottom of it. – SimonGoldstone Nov 04 '13 at 16:57

11 Answers11

24

I had the same problem. Comparing the generated HTML with a site that worked, I noticed that at the end of the document, there was this:

<script src="/bundles/jqueryval"></script>

...whereas the bundle should have been expanded like this:

<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>

I looked in App_Start/BundleConfig.cs, and sure enough, the JQuery validation bundle had not been defined in RegisterBundles. I had to add:

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                    "~/Scripts/jquery.validate*"));

Why this was missing, I don't know. I started with a new, clean project.

It's pretty shoddy that there's no compile-time error when you reference an undefined bundle. Even an always-on run-time error would be better than silent failure. So much time wasted!

EDIT: turns out I didn't have the JQuery validation scripts in my project, either. I had to add them via NuGet ("Microsoft JQuery Unobtrusive Validation").

Gary McGill
  • 26,400
  • 25
  • 118
  • 202
  • 4
    This answer helped me the most - I had the bundle defined in the App_Start/BundleConfig.cs file, BUT there wasn't a reference to using it in my _Layout.cs file. So, simply adding the @Scripts.Render("~/bundles/jquerybal") line made it all magically work. – Brett Rigby Nov 15 '14 at 09:56
  • This answer did the job for me too. Adding the @Scripts.Render was required in addition to the step above – ScottB Nov 09 '19 at 01:30
22

I was having same problem. The solution is to add .js reference to master page (_Layout.cshtml)

  1. jquery.validate.js
  2. jquery.validate.unobtrusive.js
CodeNotFound
  • 22,153
  • 10
  • 68
  • 69
user2934829
  • 667
  • 1
  • 7
  • 10
  • Sorry for delay in responding. It was already there - this is what was driving me mad. In the end the solution for me was to copy everything into a new project. – SimonGoldstone Nov 25 '13 at 17:08
  • 2
    The trick (for me) was to make sure I wasn't loading it twice... I had it on the "_Layout.cshtml" and also as part of "Scripts" at the bottom of my "view.cshtml" pages... I commented out the "Scripts" and viola... it suddenly worked as advertised. – Danimal111 Nov 28 '16 at 16:09
16

Have you verified <add key="ClientValidationEnabled" value="true" /> in web.config?

Otherwise, this provides a good overview: ASP.NET MVC 3: Required steps for unobtrusive client-side validation of dynamic/AJAX content. Also valid for MVC5.

Community
  • 1
  • 1
flip
  • 1,271
  • 14
  • 28
9

At the bottom of the page add:

@Scripts.Render("~/bundles/jqueryval")

and everything will work fine.

SharpC
  • 6,974
  • 4
  • 45
  • 40
Maulik Anand
  • 1,429
  • 3
  • 15
  • 19
3

I was having the same issue when I was playing with my first MVC project. The issue was at the end that I didn't include the input elements to the form element. Yes, very stupid. Make sure you create the form, for instance :

@using (Html.BeginForm())
{
    @Html.EditorFor(model => model.FieldA)
    @Html.ValidationMessageFor(model => model.FieldA)

    @Html.EditorFor(model => model.FieldB)
    @Html.ValidationMessageFor(model => model.FieldB)

}
veb
  • 145
  • 6
3

Since tour using MVC instead of adding to every edit view, you could add in the view/shared folder at _Layout.cshtml.

just add

@Scripts.Render("~/bundles/jqueryval")

at the bottom of _Layout.cshtml, on top of

@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/jqueryval")

in this case the script will effect every page that uses that layout.

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
2

I know this is a little late to the game but this does add more to validation and I found it to be very helpful. Sometimes conflicting javascript/jQuery Plugin/API references (eg:searchMeme.js) that reference other jquery versions can cause problems so I create unique bundles for account login actions. These are the steps I would take:

1. Create a separate layout ~/Views/Shared/_AccountLayout.cshtml for AccountController.cs.

2. Create new ~/Account/_ViewStart.csthml with:

@{
    Layout = "~/Views/Shared/_AccountLayout.cshtml";
}

3. Create two bundles for css & js in BundleConfig.cs for AccountController:

   bundles.Add(new StyleBundle("~/Content/accountcss").Include(
                "~/Content/site.css",
                "~/Content/bootstrap.css",
                "~/Content/font-awesome.css")); /*if using font-awesome */

   bundles.Add(new ScriptBundle("~/bundles/accountjs").Include(
                "~/Scripts/jquery-1.10.2.js",
                "~/Scripts/jquery.validate.js",
                "~/Scripts/jquery.validate.unobtrusive.js",
                "~/Scripts/bootstrap.js"));//must be after jquery validate

4. Reference the bundles in both ends of head & body in _AccountLayout.cshtml as such:

        <title>@ViewBag.Title</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
         @Styles.Render("~/Content/accountcss")
        @Scripts.Render("~/bundles/modernizr")
        @this.RenderSection("MetaContent", false)
        @this.RenderSection("Styles", false)
        </head>

        @Scripts.Render("~/bundles/accountjs")
        @this.RenderSection("Scripts", false)
        </body>

*NOTE: Make sure bootstrap is after jqueryval in bundle

5. Make sure you have @Html.ValidationMessageFor for each input field within ~/Account/Login.cshtml, ~/Account/Register.cshtml, etc... respectively.

<div class="form-group">
       @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
          <div class="col-md-10">
               @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
               @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
          </div>
</div>

6. Use DataAnnotations to create additional custom validation errors [RegularExpression(@"^([\w]{2,20})@?([\w]{2,20}).?[a-zA-Z]{2,3}$", ErrorMessage="")]:

[Required(ErrorMessage = "*Username is required."), RegularExpression(@"^[\w+]{3,10}\s?([\w+]{3,15})$", ErrorMessage = "*Username can only be Alphanumeric"),StringLength(25, ErrorMessage = "The {0} must be at least {2} characters long and no bigger than {1} characters.", MinimumLength = 5)]
public string UserName { get; set; }

7. (optional) Lastly, if you changed the DataAnotation for Password then you MUST also change the Password Policy in ~/App_Start/IdentityConfig.cs as such:

manager.PasswordValidator = new PasswordValidator
{
    RequiredLength = 6,
    RequireNonLetterOrDigit = false,
    RequireDigit = true,
    RequireLowercase = true,
    RequireUppercase = true,
};

8. (optional) Also, check out this article on Roles etc..

yardpenalty.com
  • 1,244
  • 2
  • 17
  • 32
1

I had the same problem, my solution is clear all history in browser (cache, cookies, form, ...) and everything work correctly.

Kien
  • 21
  • 1
  • 4
1

Hi guys this is a certain solution 1) First Add Following Items your Webconfig file

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

2) Ex(Index.cshtml) add this jquery source to up side your cshtml

<body>
 <script src="~/Content/js/jquery-1.11.1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.2/jquery.validate.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

</body>

for more https://www.youtube.com/watch?v=PLe7WbsuHPU

0

I think that @Html.ValidationMessageFor is missing from the template. I do get the errors, but not the messages.

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
jgarza
  • 556
  • 5
  • 11
  • 1
    Sorry for delay in responding. That wasn't the issue for me, unfortunately. I did I file-by-file copy and paste in to a new project and everything started working. Very strange. – SimonGoldstone Nov 25 '13 at 17:03
0

I am providing this answer for future readers.I was dealing with the same issue and found the problem is with the sequence of the render scripts. Make Sure

@Scripts.Render("~/bundles/jquery")    

is before

@Scripts.Render("~/bundles/jqueryval")

in _layout.cshtml . The layout bottom part should look like follow.

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/bootstrap")
Garry
  • 4,996
  • 5
  • 32
  • 44