将模型从视图传递给控制器净MVC

本文关键字:控制器 MVC 模型 视图 | 更新日期: 2023-09-27 18:08:46

我正在开发我的第一个ASP应用程序。. NET MVC和遇到了一个障碍,我不能弄清楚,甚至在阅读整个互联网之后。

所以我有几个视图(它们是报告),这些视图是用视图模型创建的,它们是根据用户选择标准填充的。我试图建立一个方法,接受一个模型,并导出它在Excel格式(使用EPPlus),但模型需要从这些视图之一发送。这在某种程度上是功能/可用性要求,而不是技术要求。用户可以运行报表,在查看报表后,可以单击按钮/链接,然后将创建他们正在查看的报表的Excel版本。我想传递正在显示的视图所基于的模型,因为已经根据用户的报表选择标准构建了这个特定的视图模型。

这一切都很好,我可以成功地将显示报告的视图中的模型传递给构建报告的方法。我传递的视图模型中的所有数据似乎都在那里,除了模型(IEnumerable)的集合是它的一部分。<——这就是我被困住的地方。IEnumerable的集合在断点处有0个项目,但是当创建视图模型并最初传递给视图时,绝对不是这种情况。

我卡住了,请帮忙。

View Model:

public class ReportViewModel
{
    public int ProjectId { get; set; }
    [Display(Name = "Project Name")]
    public string ProjectName { get; set; }
    [Display(Name = "Project #")]
    public string ProjectNumber { get; set; }
    public IEnumerable<SystemModel> SelectedSystems { get; set; }//has items when created and passed into the View intially, but not when the Model is passed from the View to the method/controller. 
    [Display(Name = "All Systems")]
    public bool AllSystems { get; set; }
    [Display(Name = "In Progress Systems")]
    public bool InProgressSystems { get; set; }
    [Display(Name = "Completed Systems")]
    public bool CompletedSystems { get; set; }
    [Display(Name = "Unchecked Systems")]
    public bool UncheckedSystems { get; set; }
    [Display(Name = "Systems with Problems - Ours")]
    public bool JciIssue { get; set; }
    [Display(Name = "Systems with Problems - Other's")]
    public bool OtherIssue { get; set; }
    [Display(Name = "Include Points with Problems")]
    public bool IncludePoints { get; set; }
}

视图:

    @model ProjectOps_5.ViewModels.ReportViewModel

@{
    ViewBag.Title = "Software Cx Status Report";
}
<h2>Software Cx Status Report</h2>
<div>
    <div>
        <hr />
 @Html.ActionLink("Export to Excel", "ExportExcel", Model)//call to method
//the report

方法:

    public void ExportExcel(ReportViewModel model)
        {
           //make Excel file
        }

将模型从视图传递给控制器净MVC

您不能将包含复杂对象或集合属性的模型传递给GET。在内部,ActionLink()方法调用每个属性的.ToString()方法,所以基本上DefaultModelBinder试图将属性设置为如下所示

model.SelectedSystems = "System.Collections.Generic.IEnumerable<SystemModel>";

当然失败了,属性是null

幸运的是,它不起作用,否则您将生成一个非常难看的查询字符串,并且很容易超过查询字符串限制并抛出异常。

相反,传递ProjectId属性(我假设唯一标识对象)并在ExportExcel()方法中再次获得模型

@Html.ActionLink("Export to Excel", "ExportExcel", new { ID = Model.ProjectId })

和控制器

public void ExportExcel(int ID)
{
  // Get your ReportViewModel based on the ID and do stuff
}

将整个视图模型传递给另一个方法可能不是最好的主意,因为您不知道模型的大小(SelectedSystems中的元素数量)。如果它太大,您可能超过最大请求长度或使用户等待太长时间,直到请求完成。

但如果你绝对确定这是你需要的-它可以使用一个形式:

    @using (Html.BeginForm("ExportExcel", null, FormMethod.Post))
    {
        @Html.Hidden("ProjectId", Model.ProjectId)
        @Html.Hidden("ProjectName", Model.ProjectName)
        ...
        @for(int i = 0; i < Model.SelectedSystems.Count(); i++)
        {
            var systemModel = Model.SelectedSystems.ElementAt(i);
            @Html.Hidden("SelectedSystems[" + i + "].Property1", systemModel.Property1)
            @Html.Hidden("SelectedSystems[" + i + "].Property2", systemModel.Property2)
        }
        <input type="submit" value="Export to Excel" />
    }

但是,更好的方法是使用您想要导出的所有对象的一些标识符(不确定它们在您的情况下可能是什么),并将这些id作为ActionLink路由值传递。

您可以尝试以下逻辑,您必须在发送请求之前做(或取决于您的页面,但它应该在发送请求之前可用)

var html = "";
for (index = 0; index < SelectedSystems.length; index++) {
    html += '<input type="hidden" name="SelectedSystems[' + index + '].PropertyName" id="SelectedSystems _' + index + '_PropertyName" value="YourValue"/>';
}
$("#divSelectedSystems").html(html); //Here divSelectedSystems is one dummy div with that id