2012-02-06 90 views
2

我正在使用实体框架在MVC3中工作。我有一个名为Product的实体,当用户添加新记录时,我有两个属性需要验证。要做到这一点,我创建了一个哥们类,像这样:验证MVC3中的下拉列表?

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> 
} 

(当然,上面是相当简单,只是为了避免超载代码的帖子,这不是真正相关。)

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

任何关于我做错了什么的建议将不胜感激!

TIA,

杰夫

回答

2

当你这样做:

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

你创建两个完全不同的产品()的情况下,你创建的每个属性的附加产品的情况。这可能会起作用,因为MVC只是使用lambda来创建布局格式,但它通常不是非常高效且浪费内存。

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

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

您也不需要JavaScript来设置下拉列表类型。只是这样做:

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

并确保AccountTypeId为空int和你把[Required]属性就可以了。验证器将确保有价值。

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

+0

感谢您的提示 - 我敢肯定,您可以告诉我,我对此非常青睐,所以我需要所有可以获得的指示! :-)关于你的第一点,我知道。问题是,这个视图还包含现有的产品(正如我提到的,我简化了这个张贴 - 可能太多)。也许我应该把产品创建的东西放在部分视图中?关于'AccountTypeId',底层数据库列不可为空。在这种情况下,我可以让财产为空吗? – JTennessen 2012-02-07 14:45:49

+0

局部视图的方法像一个魅力工作 - 非常感谢指出我在这个方向!我甚至没有必要使AccountTypeId为空。 :-) – JTennessen 2012-02-07 15:04:45