29

我似乎无法弄清楚如何将整个 ViewModel 发送回控制器到“验证和保存”功能。

这是我的控制器:

[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel transaction)
{
}

这是视图中的表单:

<li class="check">
    <h3>Transaction Id</h3>
     <p>@Html.DisplayFor(m => m.Transaction.TransactionId)</p>
</li>
<li class="money">
    <h3>Deposited Amount</h3>
    <p>@Model.Transaction.Amount.ToString()  BTC</p>
</li>
<li class="time">
    <h3>Time</h3>
    <p>@Model.Transaction.Time.ToString()</p>
</li>


@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { transaction = Model }))
{

@Html.HiddenFor(m => m.Token);
@Html.HiddenFor(m => m.Transaction.TransactionId);

    @Html.TextBoxFor(m => m.WalletAddress, new { placeholder = "Wallet Address", maxlength = "34" })
    <input type="submit" value="Send" />    

    @Html.ValidationMessage("walletAddress", new { @class = "validation" })
}

当我单击提交时,控制器包含 walletAddress 字段的正确值,但是,transaction.Transaction.Time是空的。transaction.Transaction.Locationtransaction.Transaction.TransactionId

有没有办法可以将整个模型传回控制器?

编辑:

当我什至没有收到walletAddress控制器中的。一切都归零!当我单独删除这一行时:@Html.HiddenFor(m => m.Transaction.TransactionId); 它可以工作并且我在控制器上获得了 Token 属性,但是当我将其添加回来时,transaction控制器上对象的所有属性都是 NULL。

这是 BitcoinTransactionViewModel:

public class BitcoinTransactionViewModel
    {
        public string Token { get; set; }
        public string WalletAddress { get; set; }
        public BitcoinTransaction Transaction { get; set; }
    }

public class BitcoinTransaction
    {
        public int Id { get; set; }
        public BitcoinTransactionStatusTypes Status { get; set; }
        public int TransactionId { get; set; }
        public decimal Amount { get; set; }
        public DateTime Time { get; set; }
        public string Location { get; set; }
    }

有任何想法吗?

编辑:我想通了,它在下面的标记答案中......

4

9 回答 9

38

好的,我一直在做其他事情,但又遇到了同样的问题。只有这一次我想出了如何让它工作!

以下是任何可能感兴趣的人的答案:

显然,有一个命名约定。注意:

这不起作用:

// Controller
[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel transaction)
{
}

// View
@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { transaction = Model }))
{

@Html.HiddenFor(m => m.Token);
@Html.HiddenFor(m => m.Transaction.TransactionId);
.
.

这有效:

// Controller
[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel **RedeemTransaction**)
{
}

// View
@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { **RedeemTransaction** = Model }))
{

@Html.HiddenFor(m => m.Token);
@Html.HiddenFor(m => m.Transaction.TransactionId);
.
.

换句话说 - 命名约定错误!Model.Transaction属性和我的transaction表单字段 + 控制器参数之间存在命名歧义。难以置信。

如果您遇到同样的问题,请确保您的控制器参数名称是唯一的 - 尝试将其重命名为 MyTestParameter 或类似的名称...

此外,如果您想将表单值发送到控制器,您需要将它们作为隐藏字段包含在内,这样就可以了。

于 2013-11-04T10:04:14.613 回答
23

表单发布到的 Send 方法的签名有一个名为 transaction 的参数,这似乎使模型绑定器感到困惑。将参数名称更改为与模型上的属性名称不匹配的名称:

[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel model)
{
}

此外,从 BeginForm 调用中删除 htmlAttributes 参数,因为这没有任何用处。它成为了:

@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post))

从客户端返回的任何数据都可能被篡改,因此您应该只回发事务的唯一 ID,然后从数据源中检索有关它的任何其他信息以执行进一步处理。您还需要在此处验证发布数据的用户是否有权访问指定的交易 ID,因为该交易 ID 也可能被篡改。

于 2013-08-23T16:07:38.313 回答
11

这不是 MVC 特定的。HTML 表单只会发布表单内的表单元素中包含的值。您的示例既不在表单内部,也不在表单元素中(例如隐藏输入)。您必须这样做,因为 MVC 不依赖于视图状态。将隐藏字段放入表单中:

@Html.HiddenFor(x => x.Transaction.Time)
// etc...

不过问问自己..如果用户没有更新这些值..您的操作方法是否需要它们?

于 2013-08-18T13:40:58.327 回答
10

模型绑定通过发布的表单值在控制器操作中水合您的视图模型。我没有看到您上述变量的任何表单控件,因此不会发回任何内容。你能看看你是否对此感到高兴吗?

@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { transaction = Model }))
{
    @Html.TextBoxFor(m => m.WalletAddress, new { placeholder = "Wallet Address", maxlength = "34" })
    @Html.Hidden("Time", Model.Transaction.Time)
    @Html.Hidden("Location", Model.Transaction.Location)
    @Html.Hidden("TransactionId", Model.Transaction.TransactionId)
    <input type="submit" value="Send" />    

    @Html.ValidationMessage("walletAddress", new { @class = "validation" })
}
于 2013-08-18T13:45:36.940 回答
4

尝试使用以下语句而不是 FOREACH 循环

<table>
    @for (var i = 0; i < Model.itemlist.Count; i++)
    {
        <tr>
            <td>
                @Html.HiddenFor(x => x.itemlist[i].Id)
                @Html.HiddenFor(x => x.itemlist[i].Name)
                @Html.DisplayFor(x => x.itemlist[i].Name)
            </td>
        </tr>
    }
</table>
于 2015-11-11T18:03:13.217 回答
1

尝试表单集合并获取值。我认为这可能有效。

public ActionResult Send(FormCollection frm)
{
    var time = frm['Transaction.Time'];
}
于 2013-08-29T13:18:15.720 回答
0

你能把你拥有的这两个模型结合起来吗?以下是我在每个视图中使用一个模型的方法... 1. 我在视图之间使用显示模板,因此我可以传递整个模型并保持数据加密.. 2. 像这样设置您的主视图...

@model IEnumerable<LecExamRes.Models.SelectionModel.GroupModel>
<div id="container"> 
<div class="selectLabel">Select a Location:</div><br />
@foreach (var item in Model)
{           
    @Html.DisplayFor(model=>item)
}
</div>

3. 在shared 中创建一个DisplayTemplates 文件夹。创建一个视图,将其命名为您想要传递的模型,因为 DisplayFor 会查找以您使用的模型命名的显示模板,我称之为我的 GroupModel。将显示模板视为枚举的对象实例。Groupmodel 看起来像这样,我只是将一个组分配给一个按钮。

@model LecExamRes.Models.SelectionModel.GroupModel
@using LecExamRes.Helpers
@using (Html.BeginForm("Index", "Home", null, FormMethod.Post))
{
 <div class="mlink">
    @Html.AntiForgeryToken()
    @Html.EncryptedHiddenFor(model => model.GroupKey)
    @Html.EncryptedHiddenFor(model => model.GroupName)
     <p>
         <input type="submit" name="gbtn" class="groovybutton" value=" @Model.GroupKey          ">
     </p>   
 </div>
}       

4. 这是控制器。 *获取和发布 *

public ActionResult Index()
    {
        // Create a new Patron object upon user's first visit to the page.
        _patron = new Patron((WindowsIdentity)User.Identity);
        Session["patron"] = _patron;            
        var lstGroups = new List<SelectionModel.GroupModel>();
        var rMgr = new DataStoreManager.ResourceManager();
        // GetResourceGroups will return an empty list if no resource groups where    found.
        var resGroups = rMgr.GetResourceGroups();
        // Add the available resource groups to list.
        foreach (var resource in resGroups)
        {
            var group = new SelectionModel.GroupModel();
            rMgr.GetResourcesByGroup(resource.Key);
            group.GroupName = resource.Value;
            group.GroupKey = resource.Key;
            lstGroups.Add(group);
        }
        return View(lstGroups);
    }

    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult Index(SelectionModel.GroupModel item)
    {
        if (!ModelState.IsValid)
            return View();

        if (item.GroupKey != null && item.GroupName != null)
        {               
            var rModel = new SelectionModel.ReserveModel
            {
                LocationKey = item.GroupKey,
                Location = item.GroupName
            };

            Session["rModel"] = rModel;
        }           
//So now my date model will have Group info in session ready to use
        return RedirectToAction("Date", "Home");
   }

5. 现在,如果我有很多不同模型的视图,我通常使用与视图相关的模型,然后使用会话 obj 从每个模型中获取数据,因此最后我有数据要提交。

于 2013-08-29T03:58:44.093 回答
0

将所有字段放入表单中

 @using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post))

并确保模型

 BitcoinTransactionViewModel

是否包含在视图中?

于 2013-08-27T09:48:07.203 回答
0

将发布数据的操作名称应与发布数据的操作名称相同。唯一的区别应该是发布数据的第二个操作应该有 [HttpPost] 并且 Posting 方法应该只服务于 Get 请求。

于 2016-02-05T08:29:17.960 回答