MVC 4 ViewModel未被发送回Controller

Uri*_*son 28 c# asp.net-mvc asp.net-mvc-4

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

这是我的控制器:

[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel transaction)
{
}
Run Code Online (Sandbox Code Playgroud)

以下是视图中的表单:

<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" })
}
Run Code Online (Sandbox Code Playgroud)

当我点击提交时,电脑板包含walletAddress字段的正确值,但是transaction.Transaction.Time,transaction.Transaction.Location,transaction.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; }
    }
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

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

Uri*_*son 35

好吧,我一直在研究其他事情并再次陷入同样的​​问题.只是这次我想出了如何让它发挥作用!

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

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

这不起作用:

// 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);
.
.
Run Code Online (Sandbox Code Playgroud)

这有效:

// 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);
.
.
Run Code Online (Sandbox Code Playgroud)

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

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

此外,如果要将表单值发送到控制器,则需要将它们作为隐藏字段包含在内,并且您可以继续使用.

  • 我喜欢这个答案,这很有意义,但不幸的是对我没有用.似乎我陷入了死胡同,无论我尝试什么,我都无法让子对象回到控制器中.这么令人沮丧的事情. (2认同)

Jon*_*tle 22

表单发布到的Send方法的签名具有名为transaction的参数,这似乎使模型绑定器混乱.将参数的名称更改为与模型上的属性名称不匹配的内容:

[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel model)
{
}
Run Code Online (Sandbox Code Playgroud)

另外,从BeginForm调用中删除htmlAttributes参数,因为它没有做任何有用的事情.它成为了:

@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post))
Run Code Online (Sandbox Code Playgroud)

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


Sim*_*ead 11

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

@Html.HiddenFor(x => x.Transaction.Time)
// etc...
Run Code Online (Sandbox Code Playgroud)

问问自己..如果用户没有更新这些值..你的行动方法是否需要它们?

  • 谢谢你的回答.我现在有一个不同的问题:当我在第一级(x => x.Token)中为属性创建一个隐藏字段时,它可以工作,但是当我为内部对象(X => x.Transaction.InnerField)执行此操作时不起作用!突然控制器中事务对象的所有属性都为null!你知道为什么会这样吗? (2认同)

Mis*_*pic 9

模型绑定通过已发布的表单值在控制器操作中对您的视图模型进行水合.我没有看到上述变量的任何表单控件,因此不会回发任何内容.你能看出你对此有什么喜悦吗?

@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" })
}
Run Code Online (Sandbox Code Playgroud)