0

我正在使用一种表格,其中包含两个表格帖子。第一个表单(“frmTemps”)成功检索数据并将其显示在表单上。我可以向您保证,当返回视图显示数据时,通过调试数据在模型中。

一旦数据返回,另一个按钮显示在同一个视图上,但第二个表单(“frmProcess”)用于对从第一个表单(“frmTemps”)返回的选定数据进行一些处理。我知道您可以在 sme View 上有多个表单。这都是 MVC 为您提供的控制的一部分。

问题是,一旦我发布我的第二个表单(“ frmProcess ”)并立即在该操作结果中设置断点并检查模型的内容,我发现模型中的所有项目要么为空,零,或假。通过对模型对象进行调试。

[HttpPost]
public ActionResult GeneratePDF(ViewModelTemplate_Guarantors model) {

我在表格 2 中使用与表格 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');

A我通过按钮 1提交了表单。模型返回并填充了我的View A. 现在我想View A用按钮 2 再次提交到同一控制器中的不同 Action 方法。

当我以我的模型作为接收参数再次将表单提交到同一个控制器时,我的模型在到达操作方法时为空。我知道我的模型在第一步返回上面时有数据。

对于 MVC 来说相对较新,我的印象是,如果您的 View 填充了数据并且您将表单提交给 Controller,那么您的 Model 中应该有数据。我现在意识到,模型不是持久的。一旦你将模型传递给视图,反之亦然,它就消失了。我得到它。

我只想知道如何在将模型提交到控制器之前用数据填充模型,以便将数据发送到控制器并填充模型以呈现视图?就是这么简单。不是 ehtat 我的模型是强类型模型。我觉得这是理解如何在视图和控制器之间提交数据的主要基石,并且对于理解 MVC 的工作原理非常重要。

当我的数据再次到达我的控制器时,我的数据为空,我做错了什么。在我提交模型将在其中包含数据的位置以便进行一些处理并再次呈现视图之前,如何将视图中的数据返回模型内部。

如果以前回发的表单上已经存在数据,那么当我通过第二个按钮再次发布时,为什么 MVC 不使用模型绑定器来创建包含表单数据的模型并发布它。

我知道 loanid 和 ddl 不会出现在数据中(因为它没有包裹在第二种形式中),但我对它的工作方式感到非常困惑。我期待它将驻留在表单上的数据发布回模型中。为什么不这样做?

4

2 回答 2

3

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

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

因此,您的数据流是:

  • 在“frmTemps”中填充值
  • 将数据从“frmTemps”发布到“刷新”操作
  • 返回带有更新模型的视图
  • 更新模型中的值填充为“frmProcess”中的隐藏字段
  • 将所有数据从“frmProcess”发布到“GeneratePDF”操作
于 2012-10-06T19:40:43.977 回答
2

有些事情要记住。

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

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

最后,通常最好有单独的视图,而不是在一个页面上组合多个表单。您可以这样做,并且在某些情况下(例如在页面上有一个搜索框)是有意义的,但总的来说它会令人困惑。

于 2012-10-06T19:54:13.993 回答