在同一页面上的form1帖子之后,使用空模型提交的净mvc 4表单成功将数据返回到同一模型

时间:2012-10-06 18:24:14

标签: .net asp.net-mvc-4

我正在使用一个包含两个表单帖子的表单。第一种形式(“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)&nbsp;@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不在数据中(因为它没有包含在第二种形式中),但我对它的工作方式感到非常困惑。我期待它将存在于表单上的数据发布到模型中。为什么不这样做?

2 个答案:

答案 0 :(得分:3)

即使表单共享模型,将提交给GeneratePDF操作的唯一值是包含在“frmProcess”表单中的值。如果您需要将“frmTemps”(例如LoanId)中的值重新提交给GeneratePDF操作,则需要将它们作为隐藏字段包含在“frmProcess”表单中。

@Html.HiddenFor(m => m.LoanId)

因此,您的数据流是:

  • 在“frmTemps”
  • 中填充值
  • 将数据从“frmTemps”发布到“刷新”操作
  • 使用更新型号返回视图
  • 更新模型中的值将填充为“frmProcess”
  • 中的隐藏字段
  • 将所有数据从“frmProcess”发布到“GeneratePDF”操作

答案 1 :(得分:2)

要记住一些事情。

首先,表单只会发布提交的表单元素中的值。如果页面上有多个表单,则其他表单中的数据不会发布。只有来自“活动”表单的数据。

如果你想要往返数据,即发布数据然后返回一个表单,然后当发布第二个表单时包含原始数据(即使它是相同的视图),那么你需要有元素来保存该数据所以它将以新的形式再次发布。隐藏字段通常用于此目的。

最后,通常最好有单独的视图,而不是在一个页面上组合多个表单。你可以做到这一点,它在某些情况下是有道理的(比如在页面上有一个搜索框),但总的来说这很令人困惑。