当我发送包含具有不同模型的多个局部视图的视图时,控制器应该接收什么?

时间:2015-03-06 22:06:58

标签: c# asp.net-mvc asp.net-mvc-4 multiple-models

当我发送包含具有不同模型的多个局部视图的视图时,控制器应该接收什么。

我有一个视图,呈现多个/动态部分视图(这些视图是根据用户先前选择的包选择的),所有这些部分视图都有不同的模型,我需要在一个大的“父”中提交它们形成。我主要担心的是控制器应该收到什么?以及如何处理表单中的所有信息,因为我有从表单发送的多个和变量模型(取决于用户选择的内容)。

这是我的父视图,它呈现所有部分视图,具体取决于用户选择的包(即父视图可以呈现1到7个表单。所有这些都具有不同的模型)。 IEnumerable字符串包含一个字符串列表,我将用它来吐出带有视图和模型的字典,以便稍后在此视图中呈现它们。

@using UI.Shared.Utils
@model IEnumerable<string>
@{
  var forms = CustomFormUtil.GetCustomMetaPartial(Model);       
}                    
@using (Html.BeginForm(MVC.Service.NewOrderRequest.Index(**I am confused what to pass here**), FormMethod.Post))
{
  foreach (var form in forms)
  {
    { Html.RenderPartial(form.View, form.Model); }
  }
  <p style="clear: both">
    <input id="submitNOR" type="submit" value="Submit" style="float: right" />
  </p>
}

因此,假设用户填写4个部分视图,这意味着我必须向控制器发送4个不同的模型,以便我可以使用用户填充的数据。

这是我的控制者:

[HttpPost]
[SaveModelState]
public virtual RedirectToRouteResult Index(**What should I receive**)
{
  if (!ModelState.IsValid)
  {
    ModelState.AddModelError("error", "Please fill out the required fields");
    return RedirectToAction(MVC.Service.NewOrderRequestForms.Index());
  }
  ...
}

我主要担心的是控制器应该收到什么?我尝试过以下方法:

[HttpPost]
[SaveModelState]
public virtual RedirectToRouteResult Index(IEnumerable<ICustomModel> models)

但经过一些研究后,这是不可能的,我也尝试将所有可能的模型传递给控制器​​

[HttpPost]
[SaveModelState]
public virtual RedirectToRouteResult Index(Model1 model1, ..., ModelN modeln)

这也行不通,我最近的尝试是创建一个包含所有可能模型的主模型并将其传递给Controller,这是我的主模型

namespace UI.Next.Areas.Service.Models
{
  public class TdlMasterModel : ICustomMetaModel
  {
    public TdlMasterModel()
    {
    }
    public TdlMasterModel(Guid? accountId)
    {
      AccountId = accountId;
    }
    public Guid? AccountId { get; set; }
    public Model1 model1{ get; set; }
    ...
    public ModelN modeln{ get; set; }
  }
}

控制器:

[HttpPost]
[SaveModelState]
public virtual RedirectToRouteResult Index(MasterModel masterModel)

到目前为止,提议的解决方案都没有奏效。 有没有直接的解决方案,或者我将不得不创建一个ModelBinder来处理这个问题。

1 个答案:

答案 0 :(得分:1)

使用包含要呈现的每个表单的模型的视图模型

查看模型

public class MasterVM
{
  public Model1 Model1 { get; set; }
  public Model2 Model2 { get; set; }
  ....
}

控制器

public ActionResult Index()
{
  MasterVM model = new MasterVM();
  // Set the values of only those models you want to display forms for
  model.Model2 = new Model2();
  return View(model);
}

[HttpPost]
public ActionResult Index(MasterVM model)
{
  if(!ModelState.IsValid)
  {
    return View();
  }
  if (model.Model1 != null)
  {
    // save Model1
  }
  else if (model.Model2 != null)
  {
    // save Model2
  }
  ....
  // redirect somewhere
}

部分_Model1.cshtml

@model Model1

@Html.LabelFor(m => m.SomeProperty)
@Html.TextBoxFor(m => m.SomeProperty)
@Html.ValidationMessageFor(m => m.SomeProperty)

@Html.LabelFor(m => m.AnotherProperty)
@Html.TextBoxFor(m => m.AnotherProperty)
@Html.ValidationMessageFor(m => m.AnotherProperty)

....

查看

@model MasterVM
@using Html.BeginForm())
{
  if(Model.Model1 != null)
  {
    @Html.Partial("_Model1", Model.Model1, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "Model1" }})
  }
  if(Model.Model2 != null)
  {
    @Html.Partial("_Model2", Model.Model2, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "Model2" }})
  }
  ....
  <input type="submit" />
}

注意@Html.Partial的第3个参数。这将为控件名称添加前缀,因此如果Model1包含属性string Name,则控件将生成为<input name="Model1.Name" ...>,允许您回发并绑定到MasterVM < / p>