表单验证并将模型传递回视图

时间:2013-11-12 23:05:01

标签: asp.net-mvc asp.net-mvc-4

我在我的viewmodel中进行了设置验证,如下所示:

[Required(ErrorMessage = "This field is required.")]
[StringLength(25, MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }

[DataType(DataType.Password)]
[System.Web.Mvc.CompareAttribute("Password", ErrorMessage = "Password must be the same")]
public string ConfirmPassword { get; set; }

当我提交表单时,我会检查ModelState.IsValid是否无效,然后返回原始视图,但这样做会丢失我在模型中的原始数据。

[HttpPost]
public ActionResult Form(MemberAddViewModel viewModel, string returnUrl)
{
    if (ModelState.IsValid)
    {

       ...
    }

    return View("Form", viewModel);
}

我原本希望将viewModel传递回原始View,但似乎只有视图中填充的模型项。这是什么最佳做法?隐藏字段/会话数据?

3 个答案:

答案 0 :(得分:1)

我不确定我是否承担了你的问题...这就是我填充丢失字段的方式:我将模型人口划分为两部分:可编辑道具(被发布回服务器的元素)和不可编辑的(丢失的)在回发上)

// View model
public class MyModel
{
    public MyModel() { }

    public MyModel(Entity e, ContractTypes[] ct)
    {
        // populate model properties from entity
        ContractTypeId = e.ContractTypeId;
        // and call magic method that'll do the rest my model needs
        PopulateNonEditableFields(ct);
    }

    public void PopulateNonEditableFields(
        Dictionary<int, string> ContractTypes [] ct)
    {
        // populate dictionaries for DDLs
        ContractTypesList = new SelectList(..., ct,...);
    }

    // model properties
    public ContractTypeId { get; set; }
    public SelectList ContractTypesList { get; set; }
}

// controller action
[HttpPost]
public ActionResult Action(MemberAddViewModel viewModel)
{
    if (ModelState.IsValid)
    {

       ...
    }
    // user input stays as-is but need to populate dictionaries and evrithing
    // that was lost on postback
    viewModel.PopulateNonEditableFields(context.ContractTypes.GetAll());
    return View("Form", viewModel);
}

答案 1 :(得分:1)

要了解为什么必须重建模型的某些部分,您需要考虑模型绑定器从视图中传递数据时发生的事情。 SelectList就是一个很好的例子。

假设您有一个视图模型如下:

public class EmployeesViewModel
{
    public int EmployeeId { get; set; }
    public SelectList Employees { get; set; }
    // other properties
}

此处,EmployeeId代表Id中所选Employee的{​​{1}}。所以我们假设你有一个这样的控制器动作,它填充SelectList并将数据传递给视图:

SelectList

现在让我们假设用户出现,导航到此视图,从列表中选择一个员工,并将数据POST回服务器。发生这种情况时,唯一从该表单提交的内容 public ActionResult Index() { var model = new EmployeesViewModel(); model.Employees = new SelectList(/* populate the list */); return View(model); } Id 。 HTTP不需要将所有其他选项从employee传输到服务器,因为a)它们尚未被选中,b)您已经在服务器上拥有该数据。

答案 2 :(得分:1)

据我了解,您在视图模型中有数据,而不是通过表单发回。出现这种情况可能有很多正当理由。

另一种方法是始终手动创建视图模型,然后通过调用TryUpdateModel使用回发值更新它。调用TryUpdateModel将做两件事:使用控制器的值提供程序设置模型的公共属性,然后对模型运行验证检查。

[HttpPost]
public ActionResult Action(int id, string returnUrl)
{
     MemberAddViewModel viewModel = CreateViewModel(id);  // Populates with 
                                                          // intial values
     if(TryUpdateModel(viewModel))
     {
         // If we got here, it passed validation
         // So we continue with the commit action
         // ...
     }
     else // It failed validation
     {
         return View("Form", viewModel);
     }
}