ASP.NET MVC服务器端验证select(下拉列表)列表所选项

时间:2015-06-19 16:41:42

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

当处理MVC中的表单帖子时,我发现自己编写了一些有些繁琐的代码,以确保发布的下拉列表选择是针对列表中的有效项目。这个想法是,没有什么能阻止包含最初未在下拉列表中显示的选定ID的帖子。用户可以将他们自己的项目插入下拉列表(或以其他方式发布他们想要的任何内容),或者表单可能已经在窗口中停留了很长时间,以至于现在可用的项目已经更改。无论它为什么会发生,事实是,您无法控制发布的数据。以下是我如何处理的一些示例代码:

VM:

public class MyViewModel
{
    public string SelectedItemID {get; set;}

    public List<Items> AvailableItems {get; set;}
}

查看:

@using (Html.BeginForm())
{
    @Html.DropDownListFor(m => m.SelectedItemID,
                                Model.AvailableItems.Select(i => new SelectListItem()
                                {
                                    Value = i.ID.ToString(),
                                    Text = i.Name,
                                    Selected = (Model.SelectedItemID == i.ID)
                                }), "Select One")
}

控制器:

[HttpPost]
public ActionResult Index(MyViewModel myVM)
{
    bool isValid = true;

    try
    {
        //Reload the available items
        myVM.AvailableItems = Repository.GetAvailableItems();

        if(!ModelState.IsValid)
        {
            isValid = false;
        }
        else
        {
            //Make sure the SelectedItemID is a real item
            if(!myVM.AvailableItems.Any(i => i.ID == myVM.SelectedItemID))
            {
                isValid = false;
                myVM.SelectedItemID = null;
                ModelState.AddModelError("SelectedItemID", "Required"); //This gets interesting when the selected ID belongs to a nested VM in a collection.
            }
        }

        if(isValid)
        {
            //Finally I can process the form
        }
    }
    catch(Exception)
    {
        ModelState.AddModelError("", "Unable to process your submission. Please try again.");
    }

    //return an ActionResult
}

如果SelectedItemID属于集合内的嵌套视图模型,则在ModelState中设置错误会特别难看。这似乎应该是标准类型的验证,但相对于在asp.net MVC中执行其他验证的简易性而言,这非常丑陋且乏味。是否有更简单的方法来处理这个问题?

1 个答案:

答案 0 :(得分:0)

我认为你应该看看Tim Coker在这里的回应:

Is it possible to update ModelState.IsValid manually?

基本上,您希望使viewmodel类继承自IValidatableObject,然后将一些验证逻辑放入其中。如果您的标准未得到满足,则后续验证调用将失败(即SelectedItemId不在新的数据库查询中)