如何在ASP.NET MVC 5中从Razor视图传递自定义模型对象到控制器操作

4

我正在编写我的第一个mvc 5生产应用程序。我试图将自定义对象作为参数传递给控制器中的http post操作。基本上,我有一个包含在我的CustomerReport视图模型中的视图,其中,我有一个部分创建了一个模态框,可以从模型中选择项目,并希望通过控制器操作保存选择,将视图模型(或视图模型的属性)作为参数传递。

我的报告视图模型

public class CustomerReport
{
    public User User { get; set; }
    public List<NewEnterprise> Enterprises { get; set; }
    public NewEnterpriseRepository EnterpriseRepository { get; set; }
    public NewCustomerRepository CustomerRepository { get; set; }
    public NewProgramRepository ProgramRepository { get; set; }
    public List<NewCustomer> Customers { get; set; }
    public List<NewProgram> Programs { get; set; }
    public List<InvoiceItem> InvoiceItems { get; set; }
    public List<ReportSelectionItem> ReportSelectionItems { get; set; }
    public List<ReportSelectionItem> FilteredSelectionItems { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Start { get; set; }
    public string End { get; set; }
    public string ReportType { get; set; }
    public NewReports Reports { get; set; }

    public CustomerReport()
    {
        User = HttpContext.Current.GetUser();
        Enterprises = new List<NewEnterprise>();
        Customers = new List<NewCustomer>();
        Programs = new List<NewProgram>();
        InvoiceItems = new List<InvoiceItem>();
        ReportSelectionItems = new List<ReportSelectionItem>();
    }

    public CustomerReport(User user)
    {
        User = user;
        Enterprises = new List<NewEnterprise>();
        Customers = new List<NewCustomer>();
        Programs = new List<NewProgram>();
        InvoiceItems = new List<InvoiceItem>();
        ReportSelectionItems = new List<ReportSelectionItem>();
        Start = Code.StringExtensions.InputDate(new DateTime(2016, 01, 01)).ToString();
        End = Code.StringExtensions.InputDate(DateTime.Today).ToString();
    }

    public CustomerReport(User user, List<NewEnterprise> enterprises, List<NewCustomer> customers, List<NewProgram> programs)
    {
        User = user;
        Enterprises = enterprises;
        Customers = customers;
        Programs = programs;
    }

    public List<ReportSelectionItem> GetAllReportSelectionItems()
    {
        var items = new List<ReportSelectionItem>();
        foreach (var ent in Enterprises)
        {
            var item = new ReportSelectionItem(ent);
            items.Add(item);
        }
        foreach (var cust in Customers)
        {
            var item = new ReportSelectionItem(cust);
            items.Add(item);
        }
        foreach (var so in Programs)
        {
            var item = new ReportSelectionItem(so);
            items.Add(item);
        }

        return items;
    }

    public List<ReportSelectionItem> ReportSelectionItemsSearch(string search)
    {
        var items = GetAllReportSelectionItems();
        var filteredItems = new List<ReportSelectionItem>();
        if (!String.IsNullOrWhiteSpace(search))
        {
            filteredItems = items.Where(i => i.DisplayName.ToLower().Contains(search.ToLower())).ToList();
            return filteredItems;
        }
        return items;
    }

    public List<ReportSelectionItem> ReportSelectionItemsFilter(List<ReportSelectionItem> items, string type)
    {
        var filteredItems = new List<ReportSelectionItem>();
        if (!type.ToLower().Equals("all"))
        {
            filteredItems = items.Where(i => i.Type.ToLower().Contains(type.ToLower())).ToList();
            return filteredItems;
        }
        return items;
    }

    public void SearchAndFilter(string search, string searchType)
    {
        if (!String.IsNullOrWhiteSpace(search))
        {
            this.FilteredSelectionItems = this.ReportSelectionItemsSearch(search);
        }
        if (!String.IsNullOrWhiteSpace(searchType))
        {
            this.FilteredSelectionItems = this.ReportSelectionItemsFilter(this.ReportSelectionItems, searchType);
        }
    }

    public void RemoveSlashFromDates(string start, string end)
    {
        if (start != null)
        {
            this.Start = start.Replace("/", "");
        }
        if (end != null)
        {
            this.End = end.Replace("/", "");
        }
    }
}

我的类用于选择列表中的项目

public class ReportSelectionItem
 {
     public Guid ID { get; set; }
     public string Name { get; set; }
     public string DisplayName { get; set; }
     public string Number { get; set; }
     public string Type { get; set; }
     public string TypeDisplay => GetTypeDisplay(Type);
     public bool IsSelected { get; set; }

     public ReportSelectionItem()
     {
         ID = Guid.NewGuid();
         IsSelected = false;
     }

     public ReportSelectionItem(NewEnterprise ent) : this()
     {
         Name = ent.Name;
         DisplayName = ent.DisplayName;
         Number = ent.EnterpriseNumber.ToString();
         Type = ent.GetType().ToString();
     }

     public ReportSelectionItem(NewCustomer cust) : this()
     {
         Name = cust.Name;
         DisplayName = cust.DisplayName;
         Number = cust.Id.ToString();
         Type = cust.GetType().ToString();
     }

     public ReportSelectionItem(NewProgram so) : this()
     {
         Name = so.Description;
         DisplayName = so.DisplayName;
         Number = so.ServiceOrderNumber.ToString();
         Type = so.GetType().ToString();
     }

     public string GetTypeDisplay(string str)
     {
         if (str.ToLower().Contains("enterprise"))
         {
             return "Enterprise";
         }else if (str.ToLower().Contains("customer"))
         {
             return "Customer";
         }else if (str.ToLower().Contains("program"))
         {
             return "Program";
         }
         else return str;
     }
 }

我主要的视图选择,用于放置模态框。
@using System.Activities.Statements
@model RecognitionReports.Web.ViewDataModels.CustomerReport

@{
  Layout = "~/Views/Shared/_Layout.cshtml";
}

<div class="row">
    <div class="col-xs-offset-1 col-xs-10">
        <div class="container">
            <div class="form-wrapper">
                <div class="search-form">
                    @using (Html.BeginForm("New", "CustomerReports", FormMethod.Get))
                    {
                        <form class="form">
                        <fieldset>
                                @Html.Label("Search:", new { @class = "form-label" })
                                <div class="form-group row">
                                    <div class="col-xs-offset-1 col-xs-10">
                                        <div class="input-group">
                                            @Html.TextBox("search", null, new { @class = "form-control", @placeholder = "Enter Selection Name or ID Number here..." })
                                            <span class="input-group-btn">
                                                <div class="btn-group">
                                                    <a href="#" class="btn btn-info dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-search"></span> Search:</a>
                                                   <ul class="dropdown-menu">
                                                        <li><input name="searchType" type="submit" id="all" value="All" class="form-control btn btn-info" /></li>
                                                        <li><input name="searchType" type="submit" id="ent" value="Enterprise" class="form-control btn btn-info" /></li>
                                                        <li><input name="searchType" type="submit" id="cust" value="Customer" class="form-control btn btn-info" /></li>
                                                        <li><input name="searchType" type="submit" id="so" value="Program" class="form-control btn btn-info" /></li>
                                                    </ul>
                                                </div>
                                            </span>
                                        </div>
                                    </div>
                                </div>
                            </fieldset>
                        </form>
                    }
                </div>

            <!-- Report Selection Modal -->
            @{ Html.RenderPartial("_ReportSelectionOptionsModal", Model);}
            <!-- Report Modal -->
            @{ Html.RenderPartial("_ReportModal", Model); }
        </div>
    </div>
</div>

我的模态视图

@model RecognitionReports.Web.ViewDataModels.CustomerReport

<div id="selection-modal" class="modal fade" role="dialog">
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal">&times;</button>
            <h4 class="modal-title">Report Selection Options</h4>
        </div>
        @using (Html.BeginForm("SaveSelections", "CustomerReports", FormMethod.Post))
        {

            <div class="modal-body">
                <table class="table table-condensed table-striped table-hover">
                    <caption>All Report Options: </caption>
                    <thead>
                        <tr>
                            <th>Display Name</th>
                            <th>Type</th>
                            <th>Manage</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var item in Model.FilteredSelectionItems)
                        {
                            <tr>
                                <td><strong>@item.DisplayName</strong></td>
                                <td>@item.TypeDisplay</td>
                                <td>
                                    @Html.CheckBoxFor(i => item.IsSelected, new { @class = "check-box", Name=item.ID, id=item.ID })
                                </td>
                            </tr>
                        }
                    </tbody>
                </table>
            </div>
            <div class="modal-footer">
                <input type="submit" class="btn btn-success" name="action" value="Save"/>
                <button type="button" class="btn btn-info" data-dismiss="modal">Close</button>
            </div>
        }
    </div>
</div>

</div>

我希望将以下内容传递给控制器

        [HttpPost]
    public ActionResult SaveSelections(CustomerReport report)
    {
        //make sure selections are saved
        return View("New", report);
    }

或者

        [HttpPost]
    public ActionResult SaveSelections(List<ReportSelectionItems> items)
    {
        //make sure selections are saved
        return View("New", report);
    }

我尝试了很多方法,但它仍然将参数传递为null。我知道razor在页面呈现后将对象属性转换为字符串,但我看到有人将自定义对象作为参数传递给控制器操作......我做错了什么?有更好的方法吗?

编辑:更新模态视图中的For循环:

@for (var i = 0; i < Model.FilteredSelectionItems.Count; i++)
  {
    <tr>
        <td><strong>@Model.FilteredSelectionItems[i].DisplayName</strong></td>
        <td>@Model.FilteredSelectionItems[i].TypeDisplay</td>
        <td>@Html.CheckBoxFor(x => Model.FilteredSelectionItems[i].IsSelected, new { @class = "check-box", Name = Model.FilteredSelectionItems[i].ID, id = Model.FilteredSelectionItems[i].ID})
            @Html.HiddenFor(x => Model.FilteredSelectionItems[i].ID)
        </td>
    </tr>
  }
1个回答

0
您表格中唯一的字段是FilteredSelectionItems属性中每个元素的复选框。因此,这是将传递到服务器的唯一信息。您可能需要稍微调整一下表单:

改为:

@foreach (var item in Model.FilteredSelectionItems)
{
    <tr>
        <td><strong>@item.DisplayName</strong></td>
        <td>@item.TypeDisplay</td>
        <td>
            @Html.CheckBoxFor(i => item.IsSelected, new { @class = "check-box", Name=item.ID, id=item.ID })
        </td>
    </tr>
}

使用这个:

@for (var i = 0; i < Model.FilteredSelectionItems.Count; i++)
{
    <tr>
        <td><strong>@item.DisplayName</strong></td>
        <td>@item.TypeDisplay</td>
        <td>
            @Html.CheckBoxFor(x => model.FilteredSelectionItems[i].IsSelected, new { @class = "check-box", Name=item.ID, id=item.ID })
        </td>
    </tr>
}

现在你的控制器操作将成功绑定到这个:

[HttpPost]
public ActionResult SaveSelections(CustomerReport report)
{
    // only report.FilteredSelectionItems collection will be available here
    // because that's the only thing you have input fields in the form
    ...
}

如果您需要填充其他字段,可以从数据库中检索它们,就像在GET操作中检索它们一样。然后与由用户从视图中选择的复选框选择填充的FilteredSelectionItems集合结果合并。

非常感谢!我已经基本解决了这个问题,但是在传递参数时它没有保留所选的值,即如果我勾选一个框并提交,传递的列表中没有任何IsSelected属性设置为true。我还尝试为reportSelectionItem ID添加了一个hiddenfor字段。 - Liveyourheart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接