UpdateModel()做什么?

时间:2011-12-22 06:38:00

标签: c# asp.net-mvc updatemodel

用外行人的话说,UpdateModel()做了什么,以及TryUpdateModel()?我似乎无法找到(在SO或网络上)任何明确的解释它实际上做了什么(用明确的术语),只是人们在使用它时遇到了问题。

VisualStudio的intellisense也没有帮助我。我问的原因是,因为,如果我在控制器中有这个:

[HttpPost]
public ActionResult Index( UserViewModel vm, FormCollection form)
{    
  var statesCheckBoxes = form["StatesList"];       

  vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>();

  return View(vm);
}

我是否已通过设置vm.BA.StatesTraveledTo来更新我的模型?为什么我需要运行UpdateModel?此外,当我实际尝试执行以下操作时:

[HttpPost]
public ActionResult Index( UserViewModel vm, FormCollection form)
{    
  var statesCheckBoxes = form["StatesList"];       

  vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>();

  UpdateModel(vm); // IS THIS REDUNDANT TO THE PREVIOUS LINE?

  return View(vm);
}

当我检查ModelState的值时(在我运行UpdateModel()之后),似乎没有发生任何事情,我没有看到任何迹象表明发生了任何变化。我没有在ModelState字典中看到新密钥。

真的很困惑。谢谢!

修改

发布ViewModel和Model类的源代码:

public class UserViewModel
{
  public BankAccount BA { get; set; }
}

public class BankAccount
{
  public Person User { get; set; }
  public List<string> StatesTraveledTo { get; set; }
}

public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public int Age { get; set; }
}

3 个答案:

答案 0 :(得分:7)

当你写

时会发生什么
public ActionResult Index( UserViewModel vm)
{    }

当您在ActionResult中进行检查时,您发现vm包含您从视图中发布的值。这是因为mvc指示模型绑定器从不同的源(表单集合,路由值,查询字符串等)中提取值并填充模型的值。但是为了实现这一点,您的表单键必须与模型中的属性名称匹配,如果是这种情况,则表明您的模型已正确填充。现在我们来看实际的问题:UpdateModel做了什么?简单的答案只不过是模型绑定。区别仅在于您明确地称之为。上述ActionResult可以像使用UpdateModel

一样重写
Public ActionResult Index ()
{
   UserViewModel vm = new UserViewModel();
   UpdateModel(vm);// it will do same thing that was previously handled automatically by mvc
}

现在,自动模型绑定未处理的内容也不会由显式模型绑定处理,因为它不是模型绑定器的问题,而是你的html问题。对于像您这样的嵌套视图模型,必须精心制作表单字段名称,以便mvc可以正确地将其注入模型,而无需编写类似

的内容
vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

如果你不想这样做,请查看google search

答案 1 :(得分:2)

以下是它的源代码:http://aspnet.codeplex.com/SourceControl/changeset/view/72551#266451

这很简单,

    protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class {
        if (model == null) {
            throw new ArgumentNullException("model");
        }
        if (valueProvider == null) {
            throw new ArgumentNullException("valueProvider");
        }

        Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties);
    IModelBinder binder = Binders.GetBinder(typeof(TModel));

    ModelBindingContext bindingContext = new ModelBindingContext() {
        Model = model,
        ModelName = prefix,
        ModelState = ModelState,
        ModelType = typeof(TModel),
        PropertyFilter = propertyFilter,
        ValueProvider = valueProvider
    };
    binder.BindModel(ControllerContext, bindingContext);
    return ModelState.IsValid;
}

这只是创建一个ModelBindingContext并绑定它。我相信在您的操作被调用之前,它已经默认发生。很少需要手动调用它。

这里只是一个猜测,但你可能会得到奇怪的结果,因为你做的事情是非典型的。你的行动签名:

public ActionResult Index( UserViewModel vm, FormCollection form)

采用UserViewModel和FormCollection。通常人们会做一个或另一个(实际上FormCollection现在非常罕见)。同样,我在这里关闭内存,但我猜想UpdateModel什么都不做,因为这些值已经绑定了。如果它是空的,那么可能是因为FormCollection接收(绑定)你的所有submittd值,并且没有一个值留给viewmodel绑定。

答案 2 :(得分:0)

更新模型主要用于更新现有模型中的新值。您无需明确指定值。