验证MVC3中的下拉列表?

时间:2012-02-06 19:52:22

标签: asp.net asp.net-mvc-3 validation

我正在使用Entity Framework在MVC3中工作。我有一个名为Product的实体,它有两个我希望在用户添加新记录时验证的属性。为此,我创建了一个好友类,如下所示:

using System;
using System.ComponentModel.DataAnnotations;

namespace Rpm.Data.Partials
{
    [MetadataType(typeof(ProductMetadata))]
    public partial class Product
    {
    }
}

元数据类如下:

using System;
using System.ComponentModel.DataAnnotations;

namespace Rpm.Data.Partials
{
    public class ProductMetadata
    {
        [Required]
        public string ProductName { get; set; }

        [Range(200, 1000, ErrorMessage = "You must select a valid Account Type")]
        public int AccountTypeId { get; set; }
    }
}

允许用户添加新记录的视图如下所示:

@model Rpm.Data.Product

@{
    ViewBag.Title = "Product"
}

<script type="text/javascript">
    $(document).ready(function() {
        //There should be no selection in the drop-down box when the form is first displayed.
        document.getElementsByTagName("select")[0].selectedIndex = -1;
    }

    function formSubmit() {
        var form = $("form");

        if (form.valid()) {
            (event.preventDefault) ? event.preventDefault() : event.returnValue = false;
            document.getElementById("frmNewProduct").submit();
            return true;
        }
        else {
            return false;
        }
    }
</script>

<h2>Add New Product</h2>

@using (Html.BeginForm("Create", "Product", new { id = new Product() }, FormMethod.Post, new { id = "frmNewProduct" }))
{
    @Html.ValidationSummary(true)
    <table>
        <tr>
            <td>
                Product Name
            </td>
            <td>
                @Html.TextBoxFor(m => new Product().ProductName)
                @Html.ValidationMessageFor(m => new Product().AccountTypeId)
            </td>
        </tr>
        <tr>
            <td>
                Account Type
            </td>
            <td>
                @Html.DropDownListFor(m => new Product().AccountTypeId, new SelectList(Lookup.Instance.AccountTypes, "AccountTypeId", "AccountTypeName"))
                @Html.ValidationMessageFor(m => new Product().AccountTypeId)
            </td>
        </tr>
        <tr>
            <td />
            <td>
                <input type="image" src="@Url.Content("~/Content/images/savebutton.png")" onclick="return formSubmit()" />
            </td>
        </tr>
    </table>
}

(当然,上面的内容非常简单,只是为了避免使用与真正无关的代码重载帖子。)

问题在于,当用户单击“保存”按钮时,ProductName的验证会正常触发,如果该字段为空,则显示验证消息;但是,即使下拉列表没有选择(selectedIndex == -1),也不会显示AccountTypeId的消息。我知道正在拾取AccountTypeId上的RangeAttribute,因为当EF尝试保存对实体的更改时,它会抛出DbEntityValidationException,而ErrorMessage的文本是我在中指定的自定义错误消息元数据。我似乎无法将其显示在页面上并导致表单验证失败,从而阻止用户保存。

对于我做错的任何建议都会非常感激!

TIA,

杰夫

1 个答案:

答案 0 :(得分:2)

执行此操作时:

@Html.TextBoxFor(m => new Product().ProductName) 
@Html.ValidationMessageFor(m => new Product().AccountTypeId) 

您将创建两个完全不同的Product()实例,并为每个属性创建其他Product实例。这可能有用,因为MVC只是使用lambda来创建一个布局格式,但它通常效率不高并浪费内存。

您的型号类型已经是产品。您应该使用m => m.ProductName

这可能会使验证系统混乱。我只是按照我的建议去做,看看问题是否还在继续。

您也不需要javascript来设置下拉列表类型。就这样做:

@Html.DropDownListFor(m => new Product().AccountTypeId, 
     new SelectList(Lookup.Instance.AccountTypes, 
         "AccountTypeId", "AccountTypeName"), "Select") 

并确保AccountTypeId是可为空的int,并在其上放置[Required]属性。验证器将确保有值。

我也不确定你为什么要使用formSubmit代码。图像输入已经是提交类型,因此当您单击它们时它们会提交表单。除了再次提交表单之外,您似乎并没有做任何事情。