默认模型绑定抛出“未为此对象定义无参数的构造函数". [英] Default model binding throwing "No paramaterless constructor defined for this object"

查看:105
本文介绍了默认模型绑定抛出“未为此对象定义无参数的构造函数".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表格,我们要为一个客户输入多个交易.表单的视图模型如下:

I have a form where we want to enter multiple deals for a single customer. The viewmodel for the form looks like this:

public class TradeSpendingEntryViewModel
{
    public TradeSpendingEntryViewModel()
    {
        Records = new List<TradeSpendingEntryViewModelRecord>();
    }

    public string CustomerNumber { get; set; }
    public DateTime Date { get; set; }
    public SelectList PlanningYears { get; set; }

    public List<TradeSpendingEntryViewModelRecord> Records { get; set; }
}

我们希望能够使用javascript动态添加和删除记录条目行.集合中的每条记录是:

We want to be able to add and remove record entry rows dynamically with javascript. Each record in the collection is:

public class TradeSpendingEntryViewModelRecord
{
    public TradeSpendingEntryViewModelRecord()
    {
    }

    public string LOB { get; set; }
    public string ProductCode { get; set; }
    public SelectList AllowType { get; set; }
    public int Cases { get; set; }
    public bool EndCurrentDeal { get; set; }
    public Single DealRate { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Comments { get; set; }
}

当我尝试将数据发布到控制器时,出现错误,指出没有为此对象定义无参数构造函数:

When I attempt to post data to my controller, I get an error indicating "No parameterless constructor defined for this object:

[HttpPost]
    public ActionResult Index(TradeSpendingEntryViewModel vm)
    {
        try
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }
            // TODO: Add insert logic here
            return View(vm);
        }
        catch
        {
            return View();
        }
    }

堆栈跟踪表明它是在模型绑定期间发生的:

Stack trace indicates it happens during the model binding:

[MissingMethodException:没有为此对象定义无参数的构造函数. System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,布尔publicOnly,布尔noCheck,布尔& canBeCached,RuntimeMethodHandleInternal& ctor,布尔&bNeedSecurityCheck)+0 System.RuntimeType.CreateInstanceSlow(布尔publicOnly,布尔skipCheckThis,布尔fillCache,StackCrawlMark& stackMark)+113 System.RuntimeType.CreateInstanceDefaultCtor(布尔publicOnly,布尔skipCheckThis,布尔fillCache,StackCrawlMark& stackMark)+232 System.Activator.CreateInstance(类型,布尔非公共)+83 System.Activator.CreateInstance(类型类型)+6 System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,type modelType)+183

[MissingMethodException: No parameterless constructor defined for this object.] System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232 System.Activator.CreateInstance(Type type, Boolean nonPublic) +83 System.Activator.CreateInstance(Type type) +6 System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +183

我的问题一定源于我如何设置视图,该视图基于本文的标记 http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

My issue must be stemming from how I've setup my view, the markup of which I have based off this article http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

@using (Html.BeginForm())
{
<header class="clearfix">
        <img src="../../Content/images/logo.png" alt="Irving Consumer Products" />
        <h1>Enter Customer Deals</h1>
    </header>
    <hr />
    <fieldset>
        <legend>Customer details</legend>
        <table>
            <tr>
                <th>
                    Date:
                </th>
                <td>
                    <input type="date" disabled="disabled" value="@DateTime.Today.ToShortDateString()" />
            </tr>
            <tr>
                <th>
                    Customer Number:
                </th>
                <td>
                    @Html.TextBoxFor(m => m.CustomerNumber, new { id = "customer-number" })
                    <a href="#" id="change-customer-number">Change me</a>
                </td>
            </tr>
            <tr>
                <th>
                    Customer Name:
                </th>
                <td>
                    <input type="text" id="customer-name" disabled="disabled" />
                </td>
                <tr>
                    <th>
                        Planning Year:
                    </th>
                    <td>
                        @Html.DropDownList("PlanningYear", Model.PlanningYears)
                        <a href="#" id="change-planning-year">Change me</a>
                    </td>
                </tr>
        </table>
    </fieldset>
    <div class="buttonGroup">
        <input type="button" value="Add line" id="add-line">
        <input type="button" value="Copy line" id="copy-line">
        <input type="button" value="Delete line" id="delete-line">
    </div>
    <hr />
    <table id="tradeSpendingEntry">
        <thead>
            <tr>
                <th>
                </th>
                <th>
                    Line of business
                </th>
                <th>
                    Product Code
                </th>
                <th>
                    Product Description
                </th>
                <th>
                    Allowance
                    <br />
                    Type
                </th>
                <th>
                    Cases
                </th>
                <th>
                    End Current Deal
                </th>
                <th>
                    Start Date
                </th>
                <th>
                    End Date
                </th>
                <th>
                    Rate
                </th>
            </tr>
        </thead>
        @foreach (var r in Model.Records)
        {
            <tbody data-entry-index="0">
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>
                    <input type="text" name="records[0].LOB" class="lobSelect" value="@r.LOB">
                </td>
                <td>
                    <!--<input type="hidden" name="records[0]ProductCodeSelected" value="@r.ProductCode" />-->
                    <input type="text" name="records[0].ProductCode" value="@r.ProductCode">
                </td>
                <td>
                    <input type="text" class="product-description" disabled="disabled" />
                </td>
                <td>
                    @Html.DropDownList("records[0].AllowType", r.AllowType)
                </td>
                <td>
                    <input name="records[0].Cases" type="number" />
                </td>
                <td>
                    <select name="records[0].EndCurrentDeal">
                        <option value="true" selected="selected">Yes</option>
                        <option value="false">No</option>
                    </select>
                </td>
                <td>
                    <input type="date" name="records[0].StartDate" />
                </td>
                <td>
                    <input type="date" name="records[0].EndDate" />
                </td>
                <td>
                    <input type="text" name="records[0].DealRate" />
                </td>
                </tr>
            <tr>
                <td></td>
                <td>
                    Comments:
                </td>
                <td colspan="8">
                    <input type="text" class="comment" name="records[0].Comments" />
                </td>
                </tr>
        </tbody>
        }
    </table>

    <footer>
        <div class="buttonGroup">
        <input type="submit" value="Submit Changes">
        <input type="button" value="Main Menu">
        <input type="button" value="View Customer Deals">
    </div>
    </footer>
    }

因此,我希望第一个字段集中的字段将映射到TradeSpendingEntryViewModel对象的即时属性(CustomerName,Date,PlanningYears).然后,对于每个表示TradeSpendingEntryViewModelRecord的对象,都将作为TradeSpendingEntryViewModel.Records集合中的项进行绑定.取而代之的是,尽管ViewModel和record对象都具有无参数构造函数,但我只是得到了一个神秘的未定义无参数构造函数"异常.

So, my hope was that the fields in the first fieldset would map to the immediate properties of the TradeSpendingEntryViewModel object (CustomerName, Date, PlanningYears). Then, for each representing a TradeSpendingEntryViewModelRecord would be bound as an item in the TradeSpendingEntryViewModel.Records collection. Instead, I just get a mysterious "No parameterless constructor defined" exception, despite both the ViewModel and the record object both having paramaterless constructors.

我的问题是,我可以使用上述文章中指示的约定使用默认模型绑定程序,还是为此目的而需要构建自定义模型绑定程序?

My question is, can I use the default model binder using the conventions indicated in the aforementioned article, or do I need to build a custom model binder for this purpose?

为完整性起见,以下是用户通过javascript向表单动态添加一行后生成的表单标记:

For completeness sake, the following is the markup of the form that gets generated after a user dynamically adds a line to the form via javascript:

<form method="post" action="/TradeSpendingEntry/Index">
<header class="clearfix">
<img alt="Irving Consumer Products" src="../../Content/images/logo.png">
<h1>Enter Customer Deals</h1>
</header>
<hr>
<fieldset>
<legend>Customer details</legend>
<table>
<tbody>
<tr>
<th> Date: </th>
<td>
<input id="dp1363608756704" class="hasDatepicker" type="date" value="18/03/2013" disabled="disabled" style="background-color: rgb(238, 238, 238);">
</td>
</tr>
<tr>
<th> Customer Number: </th>
<td>
<input id="customer-number" type="text" value="" name="CustomerNumber">
<a id="change-customer-number" href="#">Change me</a>
</td>
</tr>
<tr>
<th> Customer Name: </th>
<td>
<input id="customer-name" type="text" disabled="disabled" style="background-color: rgb(238, 238, 238);">
</td>
</tr>
<tr>
<th> Planning Year: </th>
<td>
<select id="PlanningYears" name="PlanningYears">
<option value="2011">2011</option>
<option value="2012">2012</option>
<option value="2013">2013</option>
<option value="2014">2014</option>
</select>
<a id="change-planning-year" href="#">Change me</a>
</td>
</tr>
</tbody>
</table>
</fieldset>
<div class="buttonGroup">
<input id="add-line" type="button" value="Add line">
<input id="copy-line" type="button" value="Copy line">
<input id="delete-line" type="button" value="Delete line">
</div>
<hr>
<table id="tradeSpendingEntry">
<thead>
<tr>
<th> </th>
<th> Line of business </th>
<th> Product Code </th>
<th> Product Description </th>
<th>
Allowance
<br>
Type
</th>
<th> Cases </th>
<th> End Current Deal </th>
<th> Start Date </th>
<th> End Date </th>
<th> Rate </th>
</tr>
</thead>
<tbody data-entry-index="0">
<tr>
<td>
<input type="checkbox">
</td>
<td>
<input class="lobSelect" type="text" name="records[0].LOB">
</td>
<td>
<input type="text" name="records[0].ProductCode">
</td>
<td>
<input class="product-description" type="text" disabled="disabled" style="background-color: rgb(238, 238, 238);">
</td>
<td>
<select id="records_0__AllowType" name="records[0].AllowType">
<option selected="selected">BillBack$</option>
<option>Billback%</option>
<option>O&A%</option>
<option>Coop%</option>
<option>VR%</option>
<option>Lump - O&A$</option>
<option>Lump - CP$</option>
<option>Lump - VR$</option>
<option>Lump - BB$</option>
</select>
</td>
<td>
<input type="number" name="records[0].Cases">
</td>
<td>
<select name="records[0].EndCurrentDeal">
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
</td>
<td>
<input id="dp1363608756707" class="hasDatepicker" type="date" name="records[0].StartDate">
</td>
<td>
<input id="dp1363608756708" class="hasDatepicker" type="date" name="records[0].EndDate">
</td>
<td>
<input type="text" name="records[0].DealRate">
</td>
</tr>
<tr>
<td></td>
<td> Comments: </td>
<td colspan="8">
<input class="comment" type="text" name="records[0].Comments">
</td>
</tr>
</tbody>
<tbody data-entry-index="1">
<tr>
<td>
<input type="checkbox">
</td>
<td>
<input class="lobSelect" type="text" name="records[1].LOB">
</td>
<td>
<input type="text" name="records[1].ProductCode">
</td>
<td>
<input class="product-description" type="text" disabled="disabled" style="background-color: rgb(238, 238, 238);">
</td>
<td>
<select id="records_0__AllowType" name="records[1].AllowType">
<option selected="selected">BillBack$</option>
<option>Billback%</option>
<option>O&A%</option>
<option>Coop%</option>
<option>VR%</option>
<option>Lump - O&A$</option>
<option>Lump - CP$</option>
<option>Lump - VR$</option>
<option>Lump - BB$</option>
</select>
</td>
<td>
<input type="number" name="records[1].Cases">
</td>
<td>
<select name="records[1].EndCurrentDeal">
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
</td>
<td>
<input id="dp1363608756709" class="hasDatepicker" type="date" name="records[1].StartDate">
</td>
<td>
<input id="dp1363608756710" class="hasDatepicker" type="date" name="records[1].EndDate">
</td>
<td>
<input type="text" name="records[1].DealRate">
</td>
</tr>
<tr>
<td></td>
<td> Comments: </td>
<td colspan="8">
<input class="comment" type="text" name="records[1].Comments">
</td>
</tr>
</tbody>
</table>
<footer>
<div class="buttonGroup">
<input type="submit" value="Submit Changes">
<input type="button" value="Main Menu">
<input type="button" value="View Customer Deals">
</div>
</footer>
</form>

推荐答案

毫无疑问,它是SelectList.就在昨天,我遇到了同样的问题.

Without a doubt it is the SelectList. I had the same problem just yesterday.

如果您查看SelectList,则所有其构造函数都需要一个参数. http://msdn. microsoft.com/en-us/library/system.web.mvc.selectlist(v=vs.108).aspx

If you look at the SelectList all of it's constructors require a parameter. http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist(v=vs.108).aspx

问题在于您的Action被称为public ActionResult Index(TradeSpendingEntryViewModel vm)

控制器尝试将在POST上发送回的数据绑定到TradeSpendingEntryViewModel,在该控制器上,控制器需要通过创建新的SelectList

The controller tries to bind the data sent back on POST to TradeSpendingEntryViewModel upon which it needs to set the value for PlanningYears which it tires to do by creating a new SelectList

要解决此问题,您要么需要将SelectList设置为私有变量(又称为后备字段),然后默认将其设置为空列表.这为它提供了所需的参数化构造函数:

To fix the problem, you either need to make the SelectList a private variable aka a backing field, and then set it to an empty list by default. This gives it the parameterized constructor it needs:

    //select list
    private SelectList planningYears = new SelectList(new List<YourObject>());

    public SelectList PlanningYears 
    {
        get
        {
            return planningYears;
        }
        set
        {
            locations = planningYears;
        }
    }

或将PlanningYears更改为列表<>,然后将其转换为视图上的选择列表.

Or change PlanningYears to a List<> and convert it to a select list on the view.

@Html.DropDownListFor(m => m.PlanningYears , new SelectList(Model.PlanningYears ), "choose", null)

这篇关于默认模型绑定抛出“未为此对象定义无参数的构造函数".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆