我似乎无法弄清楚如何将整个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.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; }
}
有什么想法吗?
编辑:我明白了,它在下面标记的答案中......
答案 0 :(得分: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);
.
.
这有效:
// 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
表单字段+控制器参数之间存在命名歧义。 Unvelievable。
如果您遇到同样的问题,请确保您的控制器参数名称是唯一的 - 尝试将其重命名为MyTestParameter或类似的东西......
此外,如果您想将表单值发送到控制器,您需要将它们包含在隐藏字段中,并且您可以继续使用。
答案 1 :(得分:22)
表单发布到的Send方法的签名具有名为transaction的参数,这似乎使模型绑定器混乱。将参数的名称更改为与模型上的属性名称不匹配的内容:
[HttpPost]
public ActionResult Send(BitcoinTransactionViewModel model)
{
}
此外,从BeginForm调用中删除htmlAttributes参数,因为它没有做任何有用的事情。它变成了:
@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post))
从客户端返回的任何数据都可能已被篡改,因此您只应回发事务的唯一ID,然后从数据源检索有关它的任何其他信息以执行进一步处理。您还需要在此验证发布数据的用户是否可以访问指定的事务ID,因为它也可能已被篡改。
答案 2 :(得分:11)
这不是MVC特定的。 HTML表单只会发布表单内表单元素中包含的值。您的示例既不在表单内部也不在表单元素中(例如隐藏的输入)。你必须这样做,因为MVC不依赖于View State。将隐藏字段放在表单中:
@Html.HiddenFor(x => x.Transaction.Time)
// etc...
问问自己..如果用户没有更新这些值..你的行动方法是否需要它们?
答案 3 :(得分: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" })
}
答案 4 :(得分:3)
尝试循环使用下面的语句而不是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>
答案 5 :(得分:1)
尝试表单集合并获取值。我认为这可行。
public ActionResult Send(FormCollection frm)
{
var time = frm['Transaction.Time'];
}
答案 6 :(得分:0)
将所有字段放在表单
中 @using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post))
并确保模型
BitcoinTransactionViewModel
是否包含在视图中?
答案 7 :(得分: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。在共享中创建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。这是控制器。 * GET&amp; POST *
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从每个模型中获取数据,最后我有数据要提交。
答案 8 :(得分:0)
将数据发布到的操作名称应与从中发布数据的操作名称相同。唯一的区别应该是发布数据的第二个操作应该有[HttpPost],而Posting方法应该只提供Get请求。