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

时间:2014-11-28 09:58:30

标签: c# asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 model-binding

我已经和这个人争吵了很长一段时间。一切都按计划进行,直到我尝试将View中填充的值返回给Controller(见下文):

View after populating

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

4 fields - valid

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

null is returned

在ActionResult财务中返回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>
}

显示下拉列表仍有问题:

Post from View to Controller

3 个答案:

答案 0 :(得分:2)

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

@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, ...)

答案 1 :(得分:1)

你必须这样写:

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

因为您在模型中没有InvoiceType集合属性,当您编写InvoiceType时,您在我的模型中说我有一个名为{的集合InvoiceType[0].InvoiceType {1}},其属性名称为InvoiceType,而不是

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

InvoiceType

您也可以参考此related SO post

答案 2 :(得分:1)

OMG。使用强类型帮助程序。您的控件名称都不匹配您的属性名称

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