【问题标题】:MVC Passing ViewModel to @Html.PartialMVC 将 ViewModel 传递给 @Html.Partial
【发布时间】:2015-03-28 17:29:19
【问题描述】:

将 ViewModel 传递给 @Html.Partial

有两个 ViewModel

public class RegisterVM
{
  ... some properties
  public AddressVM AddressInformation { get; set; } //viewmodel
}

public class AddressVM {
   public string Street1 { get; set; }
   public string Street2 { get; set; }
   public string PostalCode { get; set; }
}

使用 VM 加载主视图时:

    @model ViewModels.RegisterVM

所有字段加载。但是当我添加部分视图并传递视图模型时

     @Html.Partial("_AddressDetails", Model.AddressInformation)

失败了 错误:异常详细信息:System.NullReferenceException:对象引用未设置为对象的实例。为什么会失败?

部分视图 _AddressDetails 需要一个

         @model ViewModels.AddressVM 

更新

基于 Prashant 的更改,

提交信息时地址信息为NULL。 在控制器中:

    [HttpPost]
    public ActionResult Register(RegisterVM vm){
     ...
    //when viewing vm.AddressInformation.Street1 is null. and there is a value
    //Is there a different way of retrieving the values from partial view?
    }

感谢阅读。

【问题讨论】:

  • 你确定实例化了Model和Model.AddressInformation吗?
  • @VsevolodGoloviznin 你的意思是实例化模型?在控制器中,我只有 public ActionResult Register(){ return View();如果我评论 Html.Partial 行,所有字段/文本框都会毫无例外地加载
  • 您将 null 值作为模型传递,这就是您获得 NullReference 的原因

标签: asp.net-mvc viewmodel partial-views


【解决方案1】:

产生错误是因为属性AddressInformation为null,例如需要在无参构造函数或控制器中初始化它,然后再将其传递给视图,例如

public class RegisterVM
{
  public RegisterVM() // default constructor
  {
    AddressInformation = new AddressVM();
  }
  public AddressVM AddressInformation { get; set; }
  ....
}

但是你的用法意味着生成的控件将是

<input name="Street1" .../>

而他们必须是

<input name="AddressInformation.Street1" .../>

为了绑定到您的模型。您可以将您的部分设为EditorTemplate (/Views/Shared/EditorTemplates/AddressVM.cshtml) 并在主视图中用作

@Html.EditorFor(m => m.AddressInformation)

或将前缀作为附加 ViewData 传递给部分

@Html.Partial("_AddressDetails", Model.AddressInformation, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "AddressInformation" }})

【讨论】:

  • 感谢您的解释。
【解决方案2】:

这对我有用。您只需要实例化您的 VM,附加它并将其发送到视图。

页面操作

public ActionResult Page(){
     RegisterVM vm = new RegisterVM();
     vm.AddressInformation = new AddressVM();
     return View(vm);
}

Page.cshtml

@model Project.Web.Models.RegisterVM
<!-- loading partial view -->
@Html.Partial("_AddressDetails",Model.AddressInformation)

部分查看文件

<input type="text" name="name" value=" " />

【讨论】:

  • 一个可行的解决方案。不过,该局部视图示例有点令人困惑(通常 html、head 和 body 并不是局部视图的一部分)。它也缺少@model AddressVM
  • 您能解释一下为什么要在控制器中实例化模型吗?我想了解,因为如果我不调用局部视图,那么我不需要实例化模型?
  • @Ben 因为Model 是一个对象,而Model.AddressInformation 也是一个空对象,因为它没有在任何地方实例化。您需要像我一样传递它,或者您需要替换您的代码:@Html.Partial("_AddressDetails", Model.AddressInformation)@Html.Partial("_AddressDetails", new AddressInformation());
  • 我个人会使用控制器来实例化视图模型(就像 PrashantGhimire 所做的那样),并让构造函数实例化子类/对象(例如 AdressInformation)。结果是一样的。 @Ben 如果您不想/不需要传递模型,则不必。但是你不能告诉视图需要一个模型(@model xyz)然后不提供它。但它可以是空的。
  • 谢谢你的解释。@PrashantGhimire 你能看看我更新的问题。注册表已加载,但我无法检索值.. 是否有不同的方式从部分视图中检索值
【解决方案3】:

我没有关于代码的更多信息,但根据提到的细节,你可以试试这个 public ActionResult Register(){ return View(register); }

我知道您可能会尝试这样做,但尝试分配显式值。因为这是基本的 MVC 实现。如果不成功,那么您需要提供更多代码详细信息。

希望对您有所帮助。

【讨论】:

    【解决方案4】:

    在注册获取方法中必须实例化您的视图模型,因为在视图中,使用视图模型成员(属性)调用其他部分;

    public ActionResult Register(){
     RegisterVM vm = new RegisterVM();
     return View(vm);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 2013-07-14
      • 2020-10-21
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多