1

I following this tutorial for MVC data validation: http://www.tutorialsteacher.com/mvc/implement-validation-in-asp.net-mvc and somehow this is not working. Below is my code:

Model:

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

namespace LayoutProject.Models
{
    public class Book
    {
        [Required]
        public int bookId { get; set; }
        [Required]
        public String title { get; set; }
        [StringLength(50)]
        public String author { get; set; }
        [Range(0,4)]
        public int publicationYear { get; set; }
        public String editor { get; set; }
    }
}

Partial View:

@model LayoutProject.Models.Book

<h4>Books</h4>

@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(b => b.bookId)

    <table>
        <tr>
            <td>@Html.LabelFor(d=>d.bookId)</td>
            <td>@Html.TextBoxFor(d=>d.bookId)
                @Html.ValidationMessageFor(b => b.bookId, "", new { @class = "text-danger" })
            </td>
        </tr>
        <tr>
            <td>@Html.LabelFor(d=>d.title)</td>
            <td>@Html.TextBoxFor(d=>d.title)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(d=>d.author)</td>
            <td>@Html.TextBoxFor(d=>d.author)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(d=>d.publicationYear)</td>
            <td>@Html.TextBoxFor(d=>d.publicationYear)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(d=>d.editor)</td>
            <td>@Html.TextBoxFor(d=>d.editor)</td>
        </tr>
    </table>

View:

    @{
    ViewBag.Title = "CreateBooks";
}

<h2>CreateBooks</h2>

<form action="/Home/SaveBooks" method="post">
    @Html.Partial("_CreateBook")
    <input id="createBook" type="submit" value="Submit"/>
</form>

As you can see, the bookId is a required field, however when I click on the submit button without entering any bookId, I get no error message. The model would go to the controller and follow any methods written there. Any idea what I might have missed?

Controller:

    [HttpPost]
    public ActionResult SaveBooks(Book book)
    {
        return View(book);
    }
7
  • what is the controller code you have? also you are using a hidden field for book ID - are you sure that the book id is not already populated and is being posted back? Commented Oct 1, 2015 at 12:37
  • Why do you have a hidden for and text box for bookID? Commented Oct 1, 2015 at 12:40
  • 1
    bookId is typeof int which has a defaut value of 0 which means it has a value when your submit because of your hidden input (its not null) so therefore is valid Commented Oct 1, 2015 at 12:40
  • And as observed by @hjardine, no matter what you enter in the textbox for bookid, it will be ignored because your hidden input is bound to the value and the textbox value is ignored by the DefaultModelBinder (only the value of the first input is bound) Commented Oct 1, 2015 at 12:42
  • @Ahmed ilyas: I have added the controller code in my question. Commented Oct 1, 2015 at 12:44

3 Answers 3

2

From what I can gather there is two scenarios:

  1. You pre-fill the bookId in the HiddenFor and just use this to hold the ID for the form callback

OR

  1. The user can fill in the bookId using the TextBoxFor which isn't bound as the HiddenFor occurs first

Solution:

If the case is 1. - Remove TextBoxFor, LabelFor and ValidationFor bookID and ensure you are pre-filling the HiddenFor correctly (it is int so will always be valid)

If the case is 2. - Remove the HiddenFor and you should be fine.

UPDATE: As it is of type int, required will always be valid as its default state is 0

If 0 is never valid then you can do something like this:

In your Model:

[PosNumberNoZero(ErrorMessage = "A positive number, bigger than 0 is required")]
public int bookId { get; set; }

//In the same file:

public class PosNumberNoZeroAttribute : ValidationAttribute {
    public override bool IsValid(object value) {
        if (value == null) {
            return true;
        }
        int getal;
        if (int.TryParse(value.ToString(), out getal)) {

            if (getal == 0)
                return false;

            if (getal > 0)
                return true;
        }
        return false;

    }
}

Update 2: This is untested but I think you can use:

[Range(1, int.MaxValue, ErrorMessage = "Please enter a number greater than 0." )]
public int bookId { get; set; }

If 0 is valid then swap 1 for 0

Sign up to request clarification or add additional context in comments.

1 Comment

Yes I want to do client side validation only for the moment. However I tried your 2nd solution and it still does not work. Also, I am doing the same test with a String. But the form does not show any error message even when I don't fill the title field, which is a required field too.
1

It seems that you're missing jquery-validation and jquery.validate.unobtrusive script references. Try to add the following code in your view (or in your layout):

<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.js"></script>

Of course you can download them and reference them as a local files.

Also small side note - in C# the properties should be named in PascalCase (the name should starts with a capital letter and every new word starts with a capital letter).

Comments

0
[Integer]
    [Min(1, ErrorMessage="Please enter Valid bookid.")]
    [Required]
public int bookId { get; set; }

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.