Default model cast “No constructor without parameters, no restrictions for this object”

I have a form where we want to enter several transactions for one client. The view for the form is as follows:

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; } } 

We want to dynamically add and remove entries using javascript. Each entry in the collection:

 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 try to send data to my controller, I get the error "Without a constructor without parameters 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(); } } 

The stack trace indicates that this happens during model binding:

[MissingMethodException: there is no constructor without parameters for the 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.Aectivator +. System.Activator +. Mvc.DefaultModelBinder.CreateModel (ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +183

My problem should be how I set up my view, the markup of which I based on 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> } 

So, I hope that the fields in the first field set will map to the immediate properties of the TradeSpendingEntryViewModel object (CustomerName, Date, PlanningYears). Then, for each representing TradeSpendingEntryViewModelRecord it will be attached as an element in the TradeSpendingEntryViewModel.Records collection. Instead, I just get the cryptic “No parameters without constructor” exception, despite the fact that both the ViewModel and the recording object have parallel constructors.

My question is: can I use the default middleware using the conventions mentioned in the above article, or do I need to create a custom middleware for this?

For completeness of use, the following markup of the form, which is generated after the user dynamically adds a line to the form through 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> 
+4
source share
2 answers

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

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

The problem is that your Action is called public ActionResult Index(TradeSpendingEntryViewModel vm)

The controller tries to bind the data sent back to the POST to the TradeSpendingEntryViewModel , after which it needs to set the value for PlanningYears , which it gets tired of creating by creating a new SelectList

To fix this problem, you need to either make the private variable SelectList private or standby, and set the default empty list. This gives him the parameterized constructor that he needs:

  //select list private SelectList planningYears = new SelectList(new List<YourObject>()); public SelectList PlanningYears { get { return planningYears; } set { locations = planningYears; } } 

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

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

I had a better idea! Just declare the (selectList) property as a method:

follow these steps

 //fill it if whatever you want from db private List<YourList> happyList = new List<YourList>(); //that way mvc will never try to instantiate selectList on Action execution public SelectList PlanningYears() { return new SelectList(happyList,"happyID","happyDesc",""); } 

a lot of time doing properties in C # made me forget how easy it was.

-1
source

All Articles