【问题标题】:How to pass a list from view to a MVC controller如何将列表从视图传递到 MVC 控制器
【发布时间】:2016-01-01 23:13:05
【问题描述】:

我在 MVC 中有一个搜索功能来获取匹配的交易。加载事务时,将使用结果填充表。我想将此结果发布到控制器以将事务导出到 Excel 文件。问题是当我将我的视图模型发布到我的控制器时,整个视图模型是空的。我已经搜索了很多,它有很多不同的结果,但我无法让它工作。这是我的代码:

更新

查看模型:

    public class TransactionsViewModel : ViewModelBase
    {
        public TransactionsViewModel()
        {
            Charges = new List<Transaction>();
            Invoices = new List<Invoices>();
        }

        public List<Transaction> Charges { get; set; }
        public List<Invoices> Invoices { get; set; }

    [DisplayName("Telefonnummer")]
    public string PhoneNumber { get; set; }
    [DisplayName("Personnummer")]
    public string PersonalIdentityNumber { get; set; }

    [DisplayName("Ordernummer")]
    public string OrderNumber { get; set; }

    [DisplayName("Orderbeskrivning")]
    public string OrderDescription { get; set; }

    // A lot of other input format controls

public class Transaction
    {
            public string Status { get; set; }
            public DateTime Date { get; set; }
            public string Msisdn { get; set; }
            public string OrderNo { get; set; }
            public string NetsId { get; set; }
            public string Reference { get; set; }
            public string Message { get; set; }
            public decimal Amount { get; set; }
            public decimal Vat { get; set; }
            public string Merchant { get; set; }
            public decimal Fee { get; set; }
            public string PaymentType { get; set; }
            public string OrderNumber { get; set; }
            public string OrderDescription { get; set; }
    }
    }

查看

    <div id="transactionsdiv">
    @using (Html.BeginForm("SearchTransactions", "Transactions", FormMethod.Get, new { @class = "merchant-form" }))
    {
        <div class="left-col">
            <div class="form-group">
                @Html.LabelFor(model => model.PhoneNumber)
                @Html.EditorFor(model => model.PhoneNumber, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.PhoneNumber, "", new { @class = "text-danger" })
            </div>

        </div>
        <div class="form-button">
            <input type="submit" value="Sök" class="btn btn-primary" />
        </div>
    }


<div>
    @Html.Partial("ExportFiles")
</div>

导出文件

<div id="">
@using (Html.BeginForm("ExportTransactions", "Transactions", FormMethod.Post, new { @class = "merchant-form" }))
{
    <input type="submit" value="Exportera" class="btn btn-primary" />
    if (Model.Charges != null)
    {
        for (int i = 0; i < Model.Charges.Count; i++)
        {
            <input type="hidden" name="command.Transaction[i].Date" value="@(Model.Charges[i].Date)" />
            <input type="hidden" name="command.Transaction[i].Status" value="@(Model.Charges[i].Status)" />
            <input type="hidden" name="command.Transaction[i].Msisdn" value="@(Model.Charges[i].Msisdn)" />
            <input type="hidden" name="command.Transaction[i].OrderNo" value="@(Model.Charges[i].OrderNo)"/>
            <input type="hidden" name="command.Transaction[i].NetsId" value="@(Model.Charges[i].NetsId)"/>
            <input type="hidden" name="command.Transaction[i].Message" value="@(Model.Charges[i].Message)"/>
            <input type="hidden" name="command.Transaction[i].Amount" value="@(Model.Charges[i].Amount)"/>
            <input type="hidden" name="command.Transaction[i].Reference" value="@(Model.Charges[i].Reference)" />

        }
    }
}
<table id="Transaction" class="table table-striped table-bordered" width="100%" cellspacing="0" style="display: none;">
    <thead>
        <tr>
            <th>Datum</th>
            <th>Status</th>
            <th class="amount-col">Msisdn</th>
            <th>OrderNo</th>
            <th>Netsreferens</th>
            <th>Beskrivning</th>
            <th class="amount-col">Belopp</th>
            @if (Model.AllowRefund)
            {
                <th>Återköp</th>
            }
        </tr>
    </thead>
    <tbody>
        @if (Model.Charges != null)
        {
            for (int i = 0; i < Model.Charges.Count; i++)
            {
                <tr>
                    <td class="text-col">@Model.Charges[i].Date</td>
                    <td>@Model.Charges[i].Status</td>
                    <td class="amount-col">@Model.Charges[i].Msisdn</td>
                    <td>@Model.Charges[i].OrderNo</td>
                    <td>@Model.Charges[i].NetsId</td>
                    <td>@Model.Charges[i].Message</td>
                    <td class="amount-col">@Model.Charges[i].Amount</td>
                    @if (Model.AllowRefund)
                    {
                        <td>
                            @if (Model.Charges[i].Status == "Completed")
                    {
                                <a href="/Merchants/Refund?chargeId=@(Model.Charges[i].Reference)"><button type="button" class="m-button m-button-main">Återköp<    /button></a>
                            }
                            else
                            {
                                <div>&nbsp;</div>
                            }
                        </td>
                    }
                </tr>
            }

        }
        }

    </tbody>
</table>

控制器

public ActionResult ExportTransactions(TransactionsViewModel command)
    {
        return View();
    }

在此示例中未显示,但我正在使用带有 mvc 表单标签的事务表的部分视图来将该值发布到控制器。我尝试使用 for 循环而不是 for each 循环,并尝试仅插入 Html.editorFor(model => model.Charges) 来获取列表。但是每次我将模型发布到控制器时,模型都是空的。有什么建议吗?

【问题讨论】:

  • 尝试使用for 循环使输入名称遵循TransactionsViewModel.Charges[0].Transaction.PhoneNumber 等对象图的层次结构,并检查是否有任何不同。
  • 您的局部视图不会生成任何表单控件,因此没有什么要回发的。而且由于没有可编辑的内容,因此没有任何意义的表单。不清楚你想做什么。
  • 您显示的唯一控制器方法是public ActionResult ExportTransactions(TransactionsViewModel command),并且您显示的发布到该方法的唯一视图是ExportFiles.cshtml。该表单确实包含任何表单控件,所以我再次重复没有什么可以发回控制器
  • 您创建的名称属性与您的模型完全没有关系。您不会创建这样的输入-它的for (int i = 0; i &lt; Model.Charges.Count; i++) { @Html.HiddenFor(m =&gt; m.Charges[i].Status) 等。但是到底为什么要通过将大量数据发送到视图然后将其全部原封不动地重新发布来降低您的应用程序的性能,更不用说安全风险了。再次从数据库中获取数据
  • 没问题。但是为什么你接受了一个不正确的答案(它不会绑定到你的模型上)以及它对其他用户的误导?

标签: c# asp.net-mvc


【解决方案1】:

当您提交表单时,它将使用表单内输入控件的值填充请求表单数据。在您的表单中没有输入控件,因此不会发送任何内容。

将您刚刚从中获得的完整数据列表发送回服务器对我来说似乎是很多开销。我只需发回搜索参数,服务器就可以再次执行搜索并返回您需要构建的 Excel。或者,如果您的搜索速度太慢而无法再次执行,那么在数据库中查找费用(或发票)的 id 列表就足够了。

无论如何,您需要发送回服务器的内容(作为表单参数)必须在表单中。最简单的方法是为您需要发回的每个字段添加一个隐藏输入。在这种情况下,您要发送一个对象数组,因此您必须输入 create proper names

这样的事情应该可以解决问题:

导出文件

<div id="">
@using (Html.BeginForm("ExportTransactions", "Transactions", FormMethod.Post, new {@class = "merchant-form"}))
{
    <input type="submit" value="Exportera" class="btn btn-primary"/>
    @if (Model.Charges != null)
    {
        for (int i = 0; i < Model.Charges.Count; i++)
        {
            <input type="hidden" name="command.Charges[@(i)].Date" value="@Model.Charges[i].Date" />
            <input type="hidden" name="command.Charges[@(i)].Status" value="@Model.Charges[i].Status" />
            <input type="hidden" name="command.Charges[@(i)].Msisdn" value="@Model.Charges[i].Msisdn" />
            <input type="hidden" name="command.Charges[@(i)].OrderNo" value="@Model.Charges[i].OrderNo" />

            @* All the other properties of your objects that you need to send to the server on post. You get the idea... *@
        }
    }
}
<table id="Transaction" class="table table-striped table-bordered" width="100%" cellspacing="0" style="display: none;">
    <thead>
    <tr>
        <th>Datum</th>
        <th>Status</th>
        <th class="amount-col">Msisdn</th>
        <th>OrderNo</th>
        <th>Netsreferens</th>
        <th>Beskrivning</th>
        <th class="amount-col">Belopp</th>
        @if (Model.AllowRefund)
        {
            <th>Återköp</th>
        }
    </tr>
    </thead>
    <tbody>
    @if (Model.Charges != null)
    {
        for (int i = 0; i < Model.Charges.Count; i++)
        {
            <tr>
                <td class="text-col">@Model.Charges[i].Date</td>
                <td>@Model.Charges[i].Status</td>
                <td class="amount-col">@Model.Charges[i].Msisdn</td>
                <td>@Model.Charges[i].OrderNo</td>
                <td>@Model.Charges[i].NetsId</td>
                <td>@Model.Charges[i].Message</td>
                <td class="amount-col">@Model.Charges[i].Amount</td>
                @if (Model.AllowRefund)
                {
                    <td>
                        @if (Model.Charges[i].Status == "Completed")
                        {
                            <a href="/Merchants/Refund?chargeId=@(Model.Charges[i].Reference)"><button type="button" class="m-button m-button-main">Återköp<    /button></a>
                        }
                        else
                        {
                            <div>&nbsp;</div>
                        }
                    </td>
                }
            </tr>
        }

    }
    }

    </tbody>
</table>

显示数据的表格与将发布到服务器的表单无关,因此在它之外完全没问题。

请记住,隐藏输入只是对用户隐藏的输入,但它们不是只读的,因此任何有足够知识的用户都可以在发送到服务器之前更改它们,您将生成包含错误数据的 Excel。因此,我强烈建议在创建 Excel 之前使用原始参数再次执行搜索。

【讨论】:

  • Okey,所以我按照您的建议进行了更改,并尝试将数组作为输入参数类型来控制发布参数。但是当控制器方法被击中时,数组是空的。我已阅读您建议的文章并尝试过,但有些地方我无法弄清楚。它是部分视图并且 Transactionspartialview 正在发布到 Transactionsviewmodel 类型的控制器吗?对不起,如果我让你感到困惑!
  • @AndreasJangefalk 敬畏人,我知道你在努力,但我只是不认为你得到它,但别担心我在某个时候有两个,无论如何都会有帮助......当我在做这些事情......我从控制器中的“FormCollection 表单”中使用......这有助于理解控制器能够拾取什么。所以使用“public ActionResult ExportTransactions(TransactionsViewModel command, FormCollection form)”并在调整代码时检查表单。那里的其他人提供了很好的建议。
  • 有点晚了,因为我刚刚读到您再次寻求搜索解决方案。肯定是更好的解决方案。但是从您在更新的问题中显示的代码中,我看到您将隐藏输入的名称分配为 name="command.Transaction[i].Date",它应该是 name="command.Transaction[@(i )].Date" 以便写入 i 变量的值而不是字符 'i'。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多