繁体   English   中英

视图向控制器操作返回NULL(模型未绑定)

[英]View returns NULL to controller Action (Model not binding)

我已经为此苦苦挣扎了一段时间了。 一切按计划进行,直到我尝试将View中填充的值返回给Controller(请参见下文):

填充后查看

使用Fiddler,一旦我提交数据,它就会显示有效的html(请参阅下文:)

4个字段-有效

据我了解,这应该与模型绑定。 我将发回到财务 ActionResult,但这是我得到的:

返回null

在ActionResult Finance中返回NULL

我只是不明白这一点。 我将一个列表传递给视图

@model List<FinanceMVC.Models.FinanceViewModel>

我的ActionResult预期以下结果:

List<FinanceViewModel> finance

我觉得自己的模型在某个地方有问题,我已尽力找到它,但是我看不到它。 有谁之前经历过这个吗? 请有人帮忙。

请在下面查看我的代码:

我有以下模型

namespace FinanceMVC.Models
{
    //public class Finance
    //{

    //}

    public class FinanceViewModel
    {
        /*ID*/
        //[Required]
        //[Display(Name = "ID")]
        //public int ID { get; set; }

        /*BINL_BIND_ID*/
        [Required]
        [Display(Name = "Invoice Type")]
        public IEnumerable<SelectListItem> InvoiceType { get; set; }

        /*BINL_Inv_Num_Pointer*/
        [RegularExpression(@"^[0-9]*$",
                            ErrorMessage = "Email is not valid")]
        [Required]
        [Display(Name = "Invoice Number")]
        public string InvoiceNumber { get; set; }

        /*BINL_Inv_Num_Period*/
        [Required]
        [Display(Name = "Invoice Number Period")]
        public IEnumerable<SelectListItem> InvoiceNumberPeriod { get; set; }
        //public List<C_Period> InvoiceNumberPeriod { get; set; }

        /*BINL_Created*/
        [Display(Name = "Invoice Created Date")]
        [Required]
        [DataType(DataType.DateTime)]
        public DateTime InvoiceDateCreated { get; set; }

        ///*BINL_SystemInserted*/
        //[Required]
        //[Display(Name = "Invoice System Inserted")]
        //public bool InvoiceSystemInserted { get; set; }
    }

    public class C_InvoiceType
    {
        public int ID { get; set; }
        public string Description { get; set; }
    }

    public class C_Period
    {
        public int Period { get; set; }
    }

    public class ReturnInfo
    {
        string InvoiceType { get; set; }
        string InvoiceNumber { get; set; }
        string InvoiceNumberPeriod { get; set; }
        string InvoiceDateCreated { get; set; }
    }
}

查看

@model List<FinanceMVC.Models.FinanceViewModel>
@{
    ViewBag.Title = "Index";
}
@using (Html.BeginForm("Finance", "Finance", FormMethod.Post, new { @class = "form-horizontal" }))
{
    <div class="col-md-1 fade in" style="margin-left: 5%; width: 100%; font-size: 11px; height: auto;">
        <div id="div_Finance_Container" style="width: 100%; height: 80%; overflow: auto; text-align: left;" runat="server" class="scroll-pane">
            <div style="height: 500px; overflow: auto;">
                <table id="dataTable" border="0">
                    @for(int i = 0; i <Model.Count; i++)
                    {
                    <tr>
                        @Html.Label("The next recommended Invoice Number is: ", "The next recommended Invoice Number is: " + Model[i].InvoiceNumber, new { style="font-weight:bold;" })
                    </tr>

                    <br />
                    <tr class="tr_clone">
                        <td>
                            <div class="col-md-1" style="width: 20%;">
                                @Html.DropDownList("InvoiceType[" + @i + "].InvoiceType", Model[i].InvoiceType)
                            </div>
                        </td>
                        <td>
                            @Html.TextBox("InvoiceNumber[" + @i + "].InvoiceNumber", Model[i].InvoiceNumber)
                        </td>

                        <td>
                            @Html.DropDownList("InvoiceNumberPeriod[" + @i + "].InvoiceNumberPeriod", Model[i].InvoiceNumberPeriod, new { @class = "InvoiceNumberPeriod", string.Empty })
                        </td>
                        <td>
                            @Html.TextBox("InvoiceDateCreated[" + @i + "].InvoiceDateCreated", Model[i].InvoiceDateCreated, new { @class = "InvoiceDateCreated", @type = "date" })
                        </td>
                        <td>
                            <input type="button" name="add" value="Add another record" class="tr_clone_add">
                        </td>
                    </tr>
                    }

                </table>
                <input type="submit" value="Save Bulk Data" />
            </div>
        </div>
    </div>
}

控制器

public class FinanceController : Controller
{
    public ActionResult Finance()
    {
        List<C_Period> c_Per = new List<C_Period>();

        // This is only for show by default one row for insert data to the database
        List<FinanceViewModel> FinanceViewList = new List<FinanceViewModel> 
        { 
            new FinanceViewModel 
            { 
                /*ID = 0 ,*/ InvoiceType = ListInvoiceTypesForFinances() /*ReturnInvoiceType()*/, InvoiceNumber = ReturnInvoiceNumber(), InvoiceNumberPeriod = ListInvoiceNumPeriodForFinances() /*c_Per*/, InvoiceDateCreated = DateTime.Now, /*InvoiceSystemInserted = false*/
            }, 
            new FinanceViewModel 
            { 
                /*ID = 0 ,*/ InvoiceType = ListInvoiceTypesForFinances() /*ReturnInvoiceType()*/, InvoiceNumber = ReturnInvoiceNumber(), InvoiceNumberPeriod = ListInvoiceNumPeriodForFinances() /*c_Per*/, InvoiceDateCreated = DateTime.Now, /*InvoiceSystemInserted = false*/
            },
            new FinanceViewModel 
            { 
                /*ID = 0 ,*/ InvoiceType = ListInvoiceTypesForFinances() /*ReturnInvoiceType()*/, InvoiceNumber = ReturnInvoiceNumber(), InvoiceNumberPeriod = ListInvoiceNumPeriodForFinances() /*c_Per*/, InvoiceDateCreated = DateTime.Now, /*InvoiceSystemInserted = false*/
            } 
        };

        return View(FinanceViewList);
    }

    // 
    // GET: /Finance/ 

    /*Matches file name of Finance.cshtml*/
    //[HttpPost]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Finance(List<FinanceViewModel> finance)
    {
        if (ModelState.IsValid)
        {

        }

        return null;
    }

    // 
    // GET: /Finance/Welcome/ 

    //public string Index()
    //{
    //    return "This is the Welcome action method...";
    //}

    public static string ReturnInvoiceNumber()
    {
        string sQ = ""
                   + " Select Max(BINL_Inv_Num_Pointer) AS [Last Invoice Number]  \n"
                   + "   From Biller_InvoiceNum_List with(nolock) \n"
                   ;

        using (SqlConnection sCon = new SqlConnection(Application_Info.sMOB_Master_Conn()))
        {
            if (sCon.State != ConnectionState.Open)
            {
                sCon.Open();
            }

            using (SqlCommand sCmd = new SqlCommand(sQ, sCon))
            {
                using (SqlDataReader sRdr = sCmd.ExecuteReader())
                {
                    string LastInvoiceRecordNumber = "";
                    while (sRdr.Read())
                    {
                        LastInvoiceRecordNumber = (string)sRdr["Last Invoice Number"];
                    }

                    int LastInvoiceLength = LastInvoiceRecordNumber.Length;
                    int number = int.Parse(LastInvoiceRecordNumber);

                    /*Increment to get recommended next Invoice Number*/
                    number = (number + 1);

                    string IntStr = number.ToString();
                    string NextInvoiceRecordNumber = IntStr.PadLeft(LastInvoiceLength, '0');

                    return NextInvoiceRecordNumber;
                }
            }

        }
    }

    public static IEnumerable<C_InvoiceType> ReturnIType()
    {
        var srtQry = "\n"
                    + " Select ID, BIND_Description \n"
                    + " From Biller_InvoiceNum_DefSet with(nolock) \n"
                    ;

        using (var conn = new SqlConnection(Application_Info.sMOB_Master_Conn()))
        using (var objCommand = new SqlCommand(srtQry, conn) { CommandType = CommandType.Text })
        using (var dt = new DataTable())
        using (var adp = new SqlDataAdapter(objCommand))
        {
            conn.Open();
            adp.Fill(dt);
            return dt.AsEnumerable().Select(o => new C_InvoiceType
            {
                ID = o.Field<int>("ID"),
                Description = o.Field<string>("BIND_Description"),
            }).ToList();
        }
    }

    public static IEnumerable<SelectListItem> ListInvoiceTypesForFinances()
    {
        var listIVTypes = ReturnIType();

        return listIVTypes
                .Select(o => new SelectListItem
                {
                    Text = o.Description,
                    Value = o.ID.ToString()
                })
                .ToList();
    }

    public static IEnumerable<C_Period> ReturnINumPeriod()
    {
        var srtQry = "\n"
                    + " Select BINL_Inv_Num_Period \n"
                    + " From Biller_InvoiceNum_List with(nolock) \n"
                    + " Where ID = 99999 \n"
                    ;

        using (var conn = new SqlConnection(Application_Info.sMOB_Master_Conn()))
        using (var objCommand = new SqlCommand(srtQry, conn) { CommandType = CommandType.Text })
        using (var dt = new DataTable())
        using (var adp = new SqlDataAdapter(objCommand))
        {
            conn.Open();
            adp.Fill(dt);
            return dt.AsEnumerable().Select(o => new C_Period
            {
                Period = o.Field<int>("BINL_Inv_Num_Period"), 
            }).ToList();
        }
    }

    public static IEnumerable<SelectListItem> ListInvoiceNumPeriodForFinances()
    {
        var listIVTypes = ReturnINumPeriod();

        return listIVTypes
                .Select(o => new SelectListItem
                {
                    Text = o.Period.ToString(),
                    Value = o.Period.ToString()
                })
                .ToList();
    }
}

更新:

因此,更改了View @Html帮助器,如下所示:

@for(int i = 0; i <Model.Count; i++)
{
<tr>
    @Html.Label("The next recommended Invoice Number is: ", "The next recommended Invoice Number is: " + Model[i].InvoiceNumber, new { style="font-weight:bold;" })
</tr>

<br />
<tr class="tr_clone">
    <td>
        <div class="col-md-1" style="width: 20%;">
            @*@Html.DropDownList("InvoiceType[" + @i + "].InvoiceType", Model[i].InvoiceType)*@
            @Html.DropDownListFor(x => Model[i].InvoiceType, Model[i].InvoiceType)
        </div>
    </td>
    <td>
        @*@Html.TextBox("InvoiceNumber[" + @i + "].InvoiceNumber", Model[i].InvoiceNumber)*@
        @Html.TextAreaFor(x => Model[i].InvoiceNumber)
    </td>

    <td>
        @*@Html.DropDownList("InvoiceNumberPeriod[" + @i + "].InvoiceNumberPeriod", Model[i].InvoiceNumberPeriod, new { @class = "InvoiceNumberPeriod", string.Empty })*@
        @Html.DropDownListFor(x => Model[i].InvoiceNumberPeriod, Model[i].InvoiceNumberPeriod, new { @class = "InvoiceNumberPeriod", string.Empty })
    </td>
    <td>
        @*@Html.TextBox("InvoiceDateCreated[" + @i + "].InvoiceDateCreated", Model[i].InvoiceDateCreated, new { @class = "InvoiceDateCreated", @type = "date" })*@
        @Html.TextBoxFor(x => Model[i].InvoiceDateCreated, new { @class = "InvoiceDateCreated", @type = "date" })
    </td>
    <td>
        <input type="button" name="add" value="Add another record" class="tr_clone_add">
    </td>
</tr>
}

下拉列表显示仍然有问题:

从视图发布到控制器

如果使用它们,则前缀需要与操作参数的名称匹配:

@Html.TextBox("finance[" + i + "].InvoiceNumber", Model[i].InvoiceNumber)
@Html.DropDownList("finance[" + i + "].InvoiceNumberPeriod", Model[i].InvoiceNumberPeriod, new { @class = "InvoiceNumberPeriod", string.Empty })
@Html.TextBox("finance[" + i + "].InvoiceDateCreated", Model[i].InvoiceDateCreated, new { @class = "InvoiceDateCreated", @type = "date" })

尽管只有一个参数时不需要它们,在这种情况下,您可以使用:

@Html.TextBox("[" + i + "].Property", ...)

您还可以并且实际上应该使用For方法:

@Html.TextBoxFor(m => m[i].InvoiceNumber, ...)
@Html.DropDownListFor(m => m[i].InvoiceNumberPeriod, ...)
@Html.TextBoxFor(m => m[i].InvoiceDateCreated, ...)

您必须这样写:

@Html.DropDownList("[" + @i + "].InvoiceType", Model[i].InvoiceType)
@Html.TextBox("[" + @i + "].InvoiceNumber", Model[i].InvoiceNumber)
.................................
.................................

因为你没有InvoiceType集合属性在模型中具有另一个属性InvoiceType当你写InvoiceType[0].InvoiceType你说的在我的模型,我有收集与名InvoiceType其中有一个属性名InvoiceType这是不是这样的

更好的方法是使用For Helpers,它将自动将控制值与Model绑定:

@Html.DropDownListFor(x=> Model[i].InvoiceType)
@Html.TextBoxFor (x=> Model[i].InvoiceNumber)
.................................
.................................

您也可以参考此相关的SO帖子

我的天啊。 使用强类型的帮助器。 您的控件名称都不匹配您的属性名称

@Html.TextBoxFor(m => m[i].InvoiceNumber)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM