【问题标题】:dropdown list always sets modelstate invalid下拉列表总是将模型状态设置为无效
【发布时间】:2011-01-22 17:01:05
【问题描述】:

这有什么问题?

@Html.DropDownListFor(x => x.Post.CategoryId, new SelectList(Model.Categories, "ID", "CategoryName"), "-- Please select --")
@Html.ValidationMessageFor(x => x.Post.CategoryId)

当我提交表单时,模型状态无效,并且此下拉列表被标记为错误,即使我从下拉列表中选择了一个值。

(顺便说一句,CategoryId 在我的帖子表中是一个 FK) 我已经添加了这个“伙伴”类作为部分

[MetadataType(typeof(Post_Validation))]
public partial class Post
{

}

class Post_Validation
{

    [Required(ErrorMessage = "Please select a Category")]
    public int CategoryId { get; set; }

}

控制器:

// GET: /News/Add
        [Authorize]
        public ActionResult Add()
        {
            var model = new AddPostViewModel() { Categories = categoryRepository.GetAllCategories(), Post = new Post(), IsEditMode=false };
            return View(model);
        }


            //
            // POST: /News/Add
            [Authorize]
            [HttpPost]
            public ActionResult Add(AddPostViewModel model)
            {
              if (!ModelState.IsValid)
              {
              ..etc
              }
            }

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3 razor


    【解决方案1】:

    您发布的这段特定代码没有任何问题。可能有问题的是您在发布到的控制器操作中所期望的模型。例如,如果此模型与用于渲染此视图的模型不同:

    [HttpPost]
    public ActionResult Index(Post post) { ... }
    

    代替:

    [HttpPost]
    public ActionResult Index(ModelContainingPostConmtainingCategoryId post) { ... }
    

    生成的下拉列表的名称如下:name="Post.CategoryId" 并且如果您的控制器操作不采用具有名为 Post 的属性和名为 CategoryId 的属性的模型,并且此 CategoryId 属性被标记使用Required,您将获得您所描述的行为。

    其他可能的原因是您有额外的属性,这些属性是必需的,但您没有包含在您的请求中。找出这一点的方法是分析您在控制器操作中返回的模型并查看缺少的内容。在调试模式下查看ModelState 属性本身也会告诉您哪些属性存在验证错误。


    更新:

    这是一个可以用作基础的完整工作示例:

    型号:

    [MetadataType(typeof(Post_Validation))]
    public class Post
    {
        public int CategoryId { get; set; }
    }
    
    class Post_Validation
    {
        [Required(ErrorMessage = "Please select a Category")]
        public int CategoryId { get; set; }
    }
    
    public class AddPostViewModel
    {
        public IEnumerable<SelectListItem> Categories { get; set; }
        public Post Post { get; set; }
    }
    

    控制器:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var model = new AddPostViewModel()
            {
                Categories = Enumerable.Range(1, 5).Select(x => new SelectListItem
                {
                    Value = x.ToString(),
                    Text = "category " + x
                }),
                Post = new Post()
            };
            return View(model);
        }
    
        [HttpPost]
        public ActionResult Index(AddPostViewModel model)
        {
            if (!ModelState.IsValid)
            {
                ...
            }
            ...
        }
    }
    

    查看:

    @model AppName.Models.AddPostViewModel
    @{
        ViewBag.Title = "Home Page";
    }
    @using (Html.BeginForm())
    {
        @Html.DropDownListFor(x => x.Post.CategoryId, new SelectList(Model.Categories, "Value", "Text"), "-- Please select --")
        @Html.ValidationMessageFor(x => x.Post.CategoryId)
        <input type="submit" value="OK" />
    }
    

    【讨论】:

    • 模型看起来很好,当我删除类别 DDL 上的验证时,它提交正常。 CategoryId 是一个整数...这可能是个问题吗?
    • @raklos,如果您使用非整数作为下拉列表的值,则可以。而且它只会发生在可为空的整数上。如果您使用的是不可为空的整数,则在这种情况下会出现异常。 CategoryId 是否在您发布到的控制器操作中分配了一个值?
    • CategoryId 返回为 null.. ID 都是 int,查看 select 中每个选项的源值也是一个整数
    • @raklos,如果 CategoryId 被定义为 int 它不能为空。整数是值类型,值类型不能是null。它们有一个默认值,对于整数,这个默认值是0。所以问题正如我所怀疑的那样:您的绑定无法正常工作:下拉列表中的选定值未正确绑定到控制器操作中的值。当然,如果不显示您的代码,我将无法为您提供任何进一步的帮助,因为我不知道您的模型与您发布到的控制器操作看起来如何。
    • @raklos,我可以看到您对模型的更新。你忘了发布你的控制器动作是什么样子的。
    【解决方案2】:

    如果您选择的变量类型不是字符串,您的模型状态对于您的下拉菜单将始终无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 2014-01-03
      • 2010-11-04
      • 2020-01-24
      相关资源
      最近更新 更多