2

1 つのコントローラーで 2 つの個別のアクション メソッドを実行する 1 つのビューに 2 つのフォームがあります。

最初のフォーム (frmRefresh) は、データを取得してフォームに表示し、ユーザーが特定のチェックボックスを選択できるようにします。送信されると、データは ViewModel に正常に返され、フォームに適切に表示されます。テンプレート用の 11 件のレコードと保証人用の 3 件のレコードが、フォームのチェックボックスとして表示されます。

2 番目のフォーム (frmProcess) は、(上記の最初の投稿から返された) フォーム上のデータを取得する役割を果たします。ユーザーは画面上で選択を行い、コントローラー内のいくつかのロジックに対してそれを処理します。モデルに List オブジェクトがありますが、オブジェクトが複雑なため、FormCollection を使用してデータを処理できるとは思いません。基本的に、それらはチェックボックスのコレクションです。そのデータのコントローラーでの処理のため、モデルで送信する必要があるデータを実際に使用する必要があります。

2 番目のフォームを送信するとき、loanid と ddl は非表示のフィールドに配置しない限り (別のフォームにあるため) 使用できないことに気付きました --- 問題ありません。私が理解するのに非常に苦労しているのは、2番目のフォーム(frmProcess)を送信するときです。モデルビューバインダーがフォームからデータを取得してモデルに入れ、GeneratePDFアクションに送信しないのはなぜですか?方法。?

第一に、なぜこれが起こっているのかを理解するための助けが本当に必要であり、第二に、モデルデータをフォームからアクションメソッドに取り込んで処理するソリューションが本当に必要です. コントローラーでわかるように、コードの最後で、データを処理するために ViewModel でテンプレートを列挙しています。

私は仕事でこれに完全に行き詰まっており、彼らはこれを私に依存しているので、助けてください. モデルバインダーがフォームの値を取得せず、処理のためにアクションメソッドに送信しない理由がわかりません。送信時にデータをモデルに戻すための何かが欠けているようです。

以下は私の関連コードです:ViedwModel

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 = "frmRefresh" }))        {             <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) 
            </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> 
            <tr> 
                <td colspan="3"> 
                    <input type="submit" id="btnRefresh" value='Refresh' /> 
                </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>

コントローラ

    public ActionResult Index(ViewModelTemplate_Guarantors model)


     { 
                ViewBag.Error = ""; 
                model.ShowGeneratePDFBtn = false; 
                return View("Index", model); 
            } 


// used for the first form "frmRefresh"         [HttpPost] public ActionResult Refresh(ViewModelTemplate_Guarantors model)         { 
            try 
            { 
                model.Error = string.Empty; 

                bool dbHasRows = db.ChkLoanFields(Convert.ToInt32(model.LoanId)); 

                if (!dbHasRows) 
                { 
                    model.ShowGeneratePDFBtn = false; 
                    model.Error = "Details not available for this LoanId."; 
                    return View("Index",model); 
                } 
                else 
                { 
                    int TemplateCnt = 0; 
                    int GuarantorCnt = 0; 
                    //todo - modify 2nd & 3rd parms instead of hardcoding 
                    ViewModelTemplate_Guarantors tg = db.SelectViewModelTemplate_Guarantors(Convert.ToInt32(model.LoanId), "All", "All", out TemplateCnt, out GuarantorCnt); 

                    if (TemplateCnt > 0) 
                        model.Templates = tg.Templates; 
                    else  
                       model.ErrorT = "Templates not available for this LoanType."; 

                    if (GuarantorCnt > 0) 
                        model.Guarantors = tg.Guarantors; 
                    else 
                        model.ErrorG = "Guarantors not available for this LoanId."; 

                    model.ShowGeneratePDFBtn = true; 
   // right before the return here, the model is full of data.  return View("Index", model);                  } 
            } 
            catch (Exception ex) 
            { 
                throw ex; 
            } 
        }  [HttpPost]   // when I check the data here (via submission from the "frmProcess" form, the model is completely empty, null, etc... WHY???? // i NEED the model data here to perform processing in this action method.  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'); 

                //todo - 2nd parm SelectedValue of dept  
                List<sSRPTFundexDocCodes1_Test_Result> sSRPTFundexDocCodes1 = db.GetFormValues(Convert.ToInt32(model.LoanId), (model.SelectedDeptValue)); 

                if (sSRPTFundexDocCodes1 != null) 
                { 
                   foreach (PDFTemplate template in model.Templates)                     { 
                       if (template.IsChecked == true)                         {

投稿後に TemplateName がモデルに表示されない。これは正常に動作します...値(チェックボックスと対応する名前がフォームに表示されます。

ただし、GeneratePDF ボタンを投稿すると、モデルに表示されるのは、チェックボックスがオンになっている場合だけです (これは素晴らしいことです)。次のステートメント (ValueFor、DisplayFor、LabelFor、EditorFor など) の多くをいじった後、返されるテンプレート名の値は空白です。チェックボックスに対応してチェックされたテンプレートの名前が必要です。

@Html.ValueFor(モデル => Model.Templates[i].TemplateName)

どうすればこれを達成できますか? 前もって感謝します...以下は私の更新されたコードです。

ViewModel public partial class ViewModelTemplate_Guarantors 
    { 
        public ViewModelTemplate_Guarantors() 
        { 
            Templates = new List<PDFTemplate>();  
            Guarantors = new List<tGuarantor>();  
        }  

        public int SelectedTemplateId { get; set; } 
        public List<PDFTemplate> Templates { get; set; } 

        public int SelectedGuarantorId { get; set; } 
        public List<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 string Error { get; set; } 
        public string ErrorT { get; set; } 
        public string ErrorG { get; set; } 
        public bool ShowGeneratePDFBtn { get; set; } 
    }  

ビューの関連部分:

if (Model.ShowGeneratePDFBtn == true) 
            { 
                if (Model.ErrorT == string.Empty) 
                { 
            <tr> 
                <td colspan="5"> 
                    <u><b>@Html.Label("Templates:")</b></u> 
                </td> 
            </tr> 
            <tr> 
                @for (int i = 0; i < Model.Templates.Count; i++) 
                {   
                    <td> 
                        @Html.CheckBoxFor(model => Model.Templates[i].IsChecked) 
                        @Html.ValueFor(model => Model.Templates[i].TemplateName)                     </td>  
                } 

            </tr> 
                } 
                else 
                { 
            <tr> 
                <td> 
                    <b>@Html.DisplayFor(model => Model.ErrorT)</b> 
                </td> 
            </tr> 
                } 

                if (Model.ErrorG == string.Empty) 
                { 
            <tr> 
                <td colspan="5"> 
                    <u><b>@Html.Label("Guarantors:")</b></u> 
                </td> 
            </tr> 
            <tr> 
                @for (int i = 0; i < Model.Guarantors.Count; i++) 
                {  
                    <td> 
                        @Html.CheckBoxFor(model => Model.Guarantors[i].isChecked) 
                        @Html.ValueFor(model => Model.Guarantors[i].GuarantorFirstName)&nbsp;@Html.ValueFor(model => Model.Guarantors[i].GuarantorLastName)                     </td>  
                } 

            </tr> 
                } 
                else 
                { 
            <tr> 
                <td> 
                    <b>@Html.DisplayFor(model => Model.ErrorG)</b> 
                </td> 
            </tr> 
                } 
            }    
            <tr> 
                <td colspan="3"> 
                    <input type="submit" name="submitbutton" id="btnRefresh" value='Refresh' /> 
                </td> 
                @if (Model.ShowGeneratePDFBtn == true) 
                { 
                    <td> 
                        <input type="submit" name="submitbutton" id="btnGeneratePDF" value='Generate PDF' /> 
                    </td> 
                } 
            </tr> 
            <tr> 
                <td colspan="5"> 
                    @Model.Error 
                </td> 
            </tr>  

コントローラ:

public ActionResult ProcessForm(string submitbutton, ViewModelTemplate_Guarantors model, FormCollection collection)

基本的に、再び正常に動作しています。[PDF の生成] ボタンを使用してフォームを投稿すると、各チェックボックスのチェックされた値が取得されますが、モデル内のテンプレートの名前は取得されません。

ここで何かが足りないのですか?

私が提出する前のフォームは基本的に以下のようなものです。ActionResultに入ると、モデルのTemplateIDとして欠落しているチェックボックス(Form4)の名前です。

public ActionResult ProcessForm(string submitbutton, ViewModelTemplate_Guarantors model, FormCollection collection)

チェックボックス(チェックあり) Form4

@for (int i = 0; i < Model.Templates.Count; i++)
                {  
                    <td>
                        @Html.CheckBoxFor(model => Model.Templates[i].IsChecked)
                        @Html.DisplayFor(model => Model.Templates[i].TemplateName)
                    </td> 
                }
4

1 に答える 1

8

私のコメントで述べたように。モデル バインダーは IEnumerable にバインドできません。

モデルは次のようになります。

public partial class ViewModelTemplate_Guarantors 
{ 
    public ViewModelTemplate_Guarantors() {
        Templates = new List<PDFTemplate>(); // These are important, the model binder
        Guarantors = new List<tGuarantor>(); // will not instantiate nested classes
    }
    public int SelectedTemplateId { get; set; } 
    public List<PDFTemplate> Templates { get; set; } 

    public int SelectedGuarantorId { get; set; } 
    public List<tGuarantor> Guarantors { get; set; } 

    ...
}

さらに、ビューは次のようになります。

...

@for(int i = 0; i < Model.Templates.Count; i++) // should really use label, not display
{ 
    <td> 
        @Html.CheckBoxFor(model => Model.Templates[i].IsChecked) 
        @Html.DisplayFor(model => Model.Templates[i].TemplateName)
    </td>
} 

...

@for(int i = 0; i < Model.Guarantors.Count; i++)
{
    <td> 
        @Html.CheckBoxFor(model => Model.Guarantors[i].isChecked)
        @Html.DisplayFor(model => Model.Gurantors[i].GuarantorFirstName)&nbsp;@Html.DisplayFor(model => Model.Guarantors[i].GuarantorLastName)
    </td>
}

...

EditorTemplate を使用し、代わりに次のようにすることをお勧めします。

...
@Html.EditorFor(m => m.Templates)
...
@Html.EditorFor(m => m.Guarantors)
...

次に ~/Views/Shared に EditorTemplates というフォルダーを作成し、 と という 2 つのファイルを作成しTemplates.cshtmlますGuarantors.cshtml

これらのファイルでは、次のようにします。

@model PDFTemplate
<td> 
    @Html.CheckBoxFor(model => model.IsChecked) 
    @Html.DisplayFor(model => model.TemplateName) 
</td> 

@model Guarantors
<td> 
    @Html.CheckBoxFor(model => model.isChecked) 
    @Html.DisplayFor(model => model.GuarantorFirstName)&nbsp;@Html.DisplayFor(model => model.GuarantorLastName) 
</td> 

エディター テンプレートは、コレクションを自動的に反復処理し、モデル バインダーがコレクションであることを理解できるように正しい命名形式を考慮します。

于 2012-10-07T19:29:21.237 に答える