我对MVC很新,对我正在创建的表单有疑问。页面顶部有一个表格,底部有一个网格。当人们在表单中输入数据并单击按钮时,表单数据将添加到下面的网格中。
我的计划是使用BeginForm并将表单发送到HttpPost控制器方法进行处理,然后退回到视图。目前,我在视图中使用此表单:
@using (Html.BeginForm("AddRefund", "Refund", FormMethod.Post))
在控制器中,我有这个:
[HttpPost]
public ActionResult AddRefund(RefundModel refund)
{
if (ModelState.IsValid)
{
(etc...)
我的问题是控制器中的“退款”对象总是从视图空到达。从我的研究来看,似乎控制器中的模型参考只是提供模型结构,而不是从视图中接收实际模型。但是,我不明白为什么会这样,因为能够从视图中将填充的视图模型发送到控制器似乎非常有价值。
另外,你们如何处理这个问题的代码?您如何从用户收集所有这些表单提交,在表单下方的网格中将它们呈现给用户,然后最终提交页面并将网格中的所有项目插入到数据库中?
编辑:这是我的观点
@model RefundsProject.Models.RefundModel
@using (Html.BeginForm("AddRefund", "Refund", FormMethod.Post))
{
(all of the form elements are here)
<input id="button-add" type="submit" value=" Add Refund to List " />
}
最终,视图最底部会有另一个按钮,用于将用户输入网格的所有项目提交到数据库。
答案 0 :(得分:3)
从我的研究来看,似乎控制器中的模型参考只是提供模型结构,而不是从视图中接收实际模型。
这与ASP.Net MVC的设计方式完全相反。 ASP.Net附带了用于Bind data from a Form, Querystring, Ajax (Json and XML) to a strongly typed object for a Controller Method的默认ModelBinder。
我的问题是&#34;退款&#34;控制器中的对象始终从视图空到达。
这很可能是由于缺乏知识或对模型绑定器如何工作的误解。
另外,你们如何处理这个问题的代码?
我希望Ajax将RefundModel
发回控制器以验证退款。如果它是有效的,那么动态创建表格中的字段,最终model bind back to an IEnumerable/List将在新方法上验证所有退款,一次一个(再次验证数据)。
这是一个非常细分的例子(可能需要一些工作,但重要的部分在那里):
类:
public class AddRefundsViewModel
{
public RefundModel Refund { get; set; }
}
public class RefundModel
{
public string Reason { get; set; }
public Decimal Amount { get; set; }
}
方法:
public ActionResult AddRefunds()
{
var model = new AddRefundsViewModel()
model.Refund = new RefundModel();
return this.View(model);
}
[HttpPost]
public ActionResult ValidateRefund(AddRefundsViewModel model)
{
var result = new { isValid = modelState.IsValid };
return this.Json(result);
}
[HttpPost]
public ActionResult ValidateRefunds(IEnumerable<RefundModel> model)
{
var isRefundsValid = true;
foreach (var refund in model)
{
isRefundsValid = TryValidateModel(refund);
if (!isRefundsValid )
break;
}
if (isRefundsValid)
{
}
else
{
// either someone hacked the form or
// logic for refunds changed.
}
}
查看:
@model AddRefundsViewModel
// assuming RefundController
@using (Html.BeginForm("Refund", "ValidateRefunds", FormMethod.Post))
{
@html.EditFor(m => m.Refund.Reason)
@html.EditFor(m => m.Refund.Amount)
<input type="button" id="addRefundButton" name="addRefundButton" value="add"/>
<input type="submit" id="submitRefundButton" name="submitRefundButton" value="submit all"/>
}
<!-- jquery -->
$(document).ready(function()
{
$('#addRefundButton').on('click', function()
{
$.ajax({
url: '/Refund/ValidateRefund',
data: $("addRefundForm").serialize(),
success: function(result)
{
if (result.isValid)
{
// create new hidden imput elements, and grid
$("addRefundForm")[0].reset();
}
else
{
// Refund isn't valid
}
}
});
});
});
答案 1 :(得分:1)
你有点不对劲。 ViewModel和Domain Model之间存在差异。 View Model是一个用于处理视图和域(业务)之间逻辑的类。从我的研究来看,似乎控制器中的模型参考只是提供模型结构,而不是从视图中接收实际模型。但是,我不明白为什么会这样,因为能够从视图中将填充的视图模型发送到控制器似乎非常有价值。
然后是Domain Model(在.net中)这通常是一些数据容器对象(POCO)。这是贫血的。基于DDD有一点差异。
那么什么是最好的实践?
使用ViewModel对象在视图和控制器之间传输数据总是好的。
然后在控制器中,你可以使用mapper(automapper或valueinjecter)来转换它们。
现在您拥有了可以处理的域对象。
答案 2 :(得分:0)
使用ViewModels在控制器和视图之间上下传递数据是完全可以接受的。
为帮助您的模型出现空白问题,输入(例如<input id="FirstName" type="text" />
)需要具有MVC模型绑定器的名称属性,以映射您发布到RefundModel
对象的内容。在您共享的View代码中,您只显示了一个提交按钮,因此不清楚您希望映射的其他元素是否具有名称。
要修复上面的输入标记示例,您可以执行<input id="FirstName" name="FirstName" type="text" />
或使用Razor帮助程序:@Html.TextBoxFor(m => m.FirstName)