Frank Myat Thu
Frank Myat Thu

Reputation: 4474

@Html.ValidationMessageFor did not work as expected

I have a two model classes which have relationship of one to many.

public class CycleType
{
    [Required(ErrorMessage = "Cycle is required.")]
    public int CycleTypeID { get; set; }

    [Required(ErrorMessage = "Cycle Type is required.")]
    [StringLength(20, ErrorMessage = "Cycle Type may not be longer than 20 characters")]
    public string Type { get; set; }

    public List<CycleModel> CycleModels { get; set; }
}

public class CycleModel
{
    public int CycleModelID { get; set; }

    [DisplayName("Cycle Type")]
    [Required(ErrorMessage = "Cycle is required.")]
    public int CycleTypeID { get; set; }

    [Required(ErrorMessage = "Model is required.")]
    [StringLength(20, ErrorMessage = "Model may not be longer than 20 characters")]
    public string Model { get; set; }

    public virtual CycleType CycleType { get; set; }
}

Razor file.

    <div class="editor-label">
        @Html.LabelFor(model => model.CycleTypeID)
    </div>
    <div class="editor-field">            
        @Html.DropDownListFor(model => model.CycleTypeID,
                                (SelectList)ViewBag.CycleType,
                                "Select Cycle Type",
                              new { id = "ddlCycleType" })
        @Html.ValidationMessageFor(model => model.CycleTypeID)
    </div>


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

1)Fist of my problem is, Validaion function did not fire when I choose select cycle type and it only give error back as

The ViewData item that has the key 'CycleTypeID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.

2)Second problem is, When I choose one of the cycle type and put value to model more than 20 characters so that validator could check as I expected. But I get the same error message again.

The ViewData item that has the key 'CycleTypeID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.

Every suggestion will be appreciated.

Upvotes: 1

Views: 7534

Answers (2)

Frank Myat Thu
Frank Myat Thu

Reputation: 4474

Why I answer my own question is I don't want anyone to face the same problem like I already found.

First of all, Let me say to @Pankaj Upadhyay that, I really appreciate his great help. I really thank you very much @Pankaj Upadhyay.

Finally I can solve my problem by getting continuous help from @Pankaj Upadhyay.

@model CyclingClubSystem.Models.CycleModel

@{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
HtmlHelper.ClientValidationEnabled = true;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;

}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
    <legend>CycleModel</legend>

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

    <div class="editor-label">
        @Html.LabelFor(model => model.CycleTypeID)
    </div>
    <div class="editor-field">            
        @*Html.DropDownListFor(model => model.CycleTypeID,
                                (SelectList)ViewBag.CycleType,
                                "Select Cycle Type",
                           new { id = "ddlCycleType", @class = "required" })*@

        @Html.DropDownListFor(model => model.CycleTypeID,
                        (SelectList)ViewBag.CycleType,
                        "Select Cycle Type",
                      new { id = "ddlCycleType"})

        @*Html.DropDownList("CycleType", "Select Cycle Type")*@
        @Html.ValidationMessageFor(model => model.CycleTypeID)
    </div>


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

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

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Controller Class

    [HttpGet]
    public ActionResult Edit(int CycleModelID)
    {
        CycleModel cycleModel = unitOfWork_CycleModel.GenericTEntityRepository.GetByID(CycleModelID);
        //ViewBag.CycleType = new SelectList(unitOfWork_cycleType.GenericTEntityRepository.Get(orderBy: CycleTypes => CycleTypes.OrderBy(CycleType => CycleType.Type)), "CycleTypeID", "Type", cycleModel.CycleTypeID);
        ViewBag.CycleType = new SelectList(unitOfWork_cycleType.GenericTEntityRepository.Get(orderBy: CycleTypes => CycleTypes.OrderBy(CycleType => CycleType.Type)), "CycleTypeID", "Type");
        return View(cycleModel);
    }

    [HttpPost]
    public ActionResult Edit(CycleModel  _CycleModel)
    {
        if (ModelState.IsValid)
        {
            unitOfWork_CycleModel.GenericTEntityRepository.Update(_CycleModel);
            unitOfWork_CycleModel.Save();
            return RedirectToAction("Index");
        }
        ViewBag.CycleType = new SelectList(unitOfWork_cycleType.GenericTEntityRepository.Get(orderBy: CycleTypes => CycleTypes.OrderBy(CycleType => CycleType.Type)), "CycleTypeID", "Type");
        return View(_CycleModel);
    }

Finally , What I Found out ,the main reason which cause error, is that I forget to put that code at [Controller Edit Post method]

ViewBag.CycleType = new SelectList(unitOfWork_cycleType.GenericTEntityRepository.Get(orderBy: CycleTypes => CycleTypes.OrderBy(CycleType => CycleType.Type)), "CycleTypeID", "Type");

Why I can solve my problem is I get the contiuous guidance from @Pankaj Upadhyay.

Upvotes: 3

Pankaj Upadhyay
Pankaj Upadhyay

Reputation: 13594

Well this is a bug in Asp.net MVC due to which the validations don't work for DropDownListFor and TextAreaFor extension methods.

You can check the details at http://aspnet.codeplex.com/workitem/8576

So, you will need to make use of HTML.DropDownList instead of DropDownListFor and then your validations will work as expected.

Update

From your controller, pass this

ViewBag.CycleTypeId = new SelectList(db.CycleTypes, "CycleTypeId", "Type"); // db is ur context instance

And in View use this

@Html.DropDownList("CycleTypeId", String.Empty)

More Update

There is one more work-around for this problem.

Just use your original code of DropDownListFor. And then just make use of class property in it like following

 @Html.DropDownListFor(model => model.CycleTypeID,
                            (SelectList)ViewBag.CycleType,
                            "Select Cycle Type",
                          new { id = "ddlCycleType", @class = "required" })

This will make the validation work, but it will display the default message of The field is required. But else will work as you expect it to be.

I guess this is a better solution and good one for your requirements.

Upvotes: 5

Related Questions