我正在使用一个包含两个表单帖子的表单。第一种形式(“frmTemps”)成功地恢复数据并将其显示在表单上。我可以向您保证,当回到View以显示数据时,通过调试数据就在模型中。
一旦数据返回,另一个按钮显示在同一个视图上,但是第二个形式(“frmProcess”)对从第一个表单(“frmTemps”)返回的seclectedd数据进行某些处理。我知道你可以在sme视图上有多种形式。它是MVC为您提供控制的所有部分。
问题在于,只要我发布第二个表单(“ frmProcess ”)并在该操作结果中立即设置断点,我就会检查内容在模型中,我发现模型中的所有项都是null,zero或false。通过对模型对象进行调试。
[HttpPost]
public ActionResult GeneratePDF(ViewModelTemplate_Guarantors model) {
我在form2中使用与我在表单1中相同的模型。
我认为可以理解的是,在填写表单上的数据之后,在提交表单并让您的模型类型在操作方法中接收之后,这是执行操作的标准方法。
下面是我的ViewModel。
public partial class ViewModelTemplate_Guarantors
{
public int SelectedTemplateId { get; set; }
public IEnumerable<PDFTemplate> Templates { get; set; }
public int SelectedGuarantorId { get; set; }
public IEnumerable<tGuarantor> Guarantors { get; set; }
public string LoanId { get; set; }
public string SelectedDeptText { get; set; }
public string SelectedDeptValue { get; set; }
public string LoanType { get; set; }
public bool ShowTemps { get; set; }
public string Error { get; set; }
public string ErrorT { get; set; }
public string ErrorG { get; set; }
public bool ShowGeneratePDFBtn { get; set; }
}
以下是我的观点:
@model PDFConverterModel.ViewModels.ViewModelTemplate_Guarantors
@{
ViewBag.Title = "BHG :: PDF Generator";
}
<h2>@ViewBag.Message</h2>
<div>
<table style="width: 1000px">
<tr>
<td colspan="5">
<img alt="BHG Logo" src="~/Images/logo.gif" />
</td>
</tr>
@using (Html.BeginForm("Refresh", "Home", FormMethod.Post, new { id = "frmTemps" }))
{
<tr>
<td>
@*@(Html.Kendo().NumericTextBox<int>()
.Name("txtLoanID")
.Placeholder("Enter numeric value")
)*@
@Html.LabelFor(model => model.LoanId)
@Html.TextBoxFor(model => model.LoanId)
@Html.ValidationMessageFor(model => model.LoanId)
<td colspan="3">
<input type="submit" id="btnRefresh" value='Refresh' />
</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.LoanType)
@Html.TextBox("SBA", "SBA")
@Html.ValidationMessageFor(model => model.LoanType)
@*@Html.TextBoxFor(model => model.LoanType)*@
</td>
<td>
<label for="ddlDept">Department:</label>
@(Html.Kendo().DropDownListFor(model => model.SelectedDeptText)
.Name("ddlDept")
.DataTextField("DepartmentName")
.DataValueField("DepartmentID")
.Events(e => e.Change("Refresh"))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetDepartments", "Home");
});
})
)
@Html.ValidationMessageFor(model => model.SelectedDeptText)
</td>
</tr>
}
@using (Html.BeginForm("GeneratePDF", "Home", FormMethod.Post, new { id = "frmProcess" }))
{
if (Model.ShowGeneratePDFBtn == true)
{
if (Model.ErrorT != string.Empty)
{
<tr>
<td colspan="5">
<u><b>@Html.Label("Templates:")</b></u>
</td>
</tr>
<tr>
@foreach (var item in Model.Templates)
{
<td>
@Html.CheckBoxFor(model => item.IsChecked)
@Html.DisplayFor(model => item.TemplateName)
</td>
}
</tr>
}
else
{
Model.Error = Model.ErrorT;
}
if (Model.ErrorG != string.Empty)
{
<tr>
<td colspan="5">
<u><b>@Html.Label("Guarantors:")</b></u>
</td>
</tr>
<tr>
@foreach (var item in Model.Guarantors)
{
<td>
@Html.CheckBoxFor(model => item.isChecked)
@Html.DisplayFor(model => item.GuarantorFirstName) @Html.DisplayFor(model => item.GuarantorLastName)
</td>
}
</tr>
}
else
{
Model.Error = Model.ErrorG;
}
<tr>
<td>
<input type="submit" id="btnGeneratePDF" value='Generate PDF' />
</td>
</tr>
<tr>
<td colspan="5">
@Model.Error
</td>
</tr>
}
}
</table>
</div>
<script type="text/javascript">
$('btnRefresh').on('click', '#btnRefresh', function () {
Refresh();
});
function Refresh() {
var LoanID = $("#LoanID").val();
if (LoanID != "") {
document.forms["frmTemps"].submit();
}
}
</script>
下面是控制器的相关部分:
[HttpPost]
public ActionResult GeneratePDF(ViewModelTemplate_Guarantors **model**)
{
try
{
int FolderNo, GuarantorNum = 0;
string Folder, LoanFolder = String.Empty;
string FormId, FormName, GuarantorName = String.Empty;
int LoanId = Convert.ToInt32(model.LoanId);
LoanFolder = LoanId.ToString().PadLeft(8, '0');
//To calculate FolderId based on LoanId
if ((LoanId > 0) && (LoanId < 99000))
{
FolderNo = ((int)(LoanId / 10000) * 10000);
}
else
{
FolderNo = ((int)(LoanId / 1000) * 1000);
}
Folder = ((int)FolderNo).ToString();
Folder = Folder.PadLeft(8, '0');
我通过按钮1提交了表单A
。模型返回并填充了我的View A
。现在我想再次使用按钮2将View A
提交到同一控制器中的不同Action方法。
当我使用我的模型作为接收参数将表单再次提交给同一个Controller时,我的模型在进入action方法时为空。我知道我的模型在第一步回到上面时会有数据。
对于MVC来说相对较新,我的印象是如果您的View填充了数据并且您将表单提交给Controller,那么Model应该包含数据。我现在意识到,模型不是持久的。一旦你将模型传递给视图,反之亦然,它就消失了。我明白了。
我想知道的是,在将数据提交给Controller之前,如何使用数据填充模型,以便将数据发送到Controller,并填充我的模型以呈现视图?就这么简单。不是我的模型是强类型模型。我觉得这是了解我如何提交数据的重要基石。意见与观点之间控制器对于理解MVC如何工作非常重要。
当我的数据再次进入我的控制器时,我的数据是空的,我做错了什么。在我提交模型中的数据之前,如何从模型中获取View中的数据,以便进行一些处理并再次渲染View。
如果有数据已经存在于上一次回发的表单中,那么当我再次通过第二个按钮发布时,为什么MVC不使用模型绑定器来创建包含表单数据的模型并发布它。 / p>
我知道loanid和ddl不在数据中(因为它没有包含在第二种形式中),但我对它的工作方式感到非常困惑。我期待它将存在于表单上的数据发布到模型中。为什么不这样做?
答案 0 :(得分:3)
即使表单共享模型,将提交给GeneratePDF操作的唯一值是包含在“frmProcess”表单中的值。如果您需要将“frmTemps”(例如LoanId)中的值重新提交给GeneratePDF操作,则需要将它们作为隐藏字段包含在“frmProcess”表单中。
@Html.HiddenFor(m => m.LoanId)
因此,您的数据流是:
答案 1 :(得分:2)
要记住一些事情。
首先,表单只会发布提交的表单元素中的值。如果页面上有多个表单,则其他表单中的数据不会发布。只有来自“活动”表单的数据。
如果你想要往返数据,即发布数据然后返回一个表单,然后当发布第二个表单时包含原始数据(即使它是相同的视图),那么你需要有元素来保存该数据所以它将以新的形式再次发布。隐藏字段通常用于此目的。
最后,通常最好有单独的视图,而不是在一个页面上组合多个表单。你可以做到这一点,它在某些情况下是有道理的(比如在页面上有一个搜索框),但总的来说这很令人困惑。