11

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

VisualStudio 的智能感知也没有帮助我。我问的原因是,比方说,如果我的控制器中有这个:

[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; }
}
4

3 回答 3

7

当你写作时会发生什么

public ActionResult Index( UserViewModel vm)
{    }

当您检查时,ActionResult您会发现其中vm包含您从视图中发布的值。这是因为 mvc 指示 modelbinder 从不同来源(表单集合、路由值、查询字符串等)提取值并填充模型的值。但是要发生这种情况,您的表单键必须与模型中的属性名称匹配,如果是这种情况,您的模型已正确填充。现在我们来看看实际的问题: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>(); 

如果你不想做这样的事情检查这个谷歌搜索

于 2011-12-22T11:08:48.367 回答
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 值,并且没有留下任何视图模型绑定到。

于 2011-12-22T06:57:43.877 回答
0

更新模型基本上用于更新现有模型中的新值。您不需要明确分配值。

于 2011-12-22T07:00:17.433 回答