4

I get the following error when I hit the postback:

The model item passed into the dictionary is of type 'Test.Models.ProductsModel', but this dictionary requires a model item of type 'Test.Models.AttributeModel'

What I want to achieve is hopefully pretty selfexplanatory with the code below

 public class ProductsModel
 {
    [Required]
    public string Name { get; set; }

    public AttributeModel AttributeModel { get; set; }
}

public class AttributeModel
{
    [Required]
    public int Size { get; set; }
}

Create.cshtml

@model Test.Models.ProductsModel      
@using (Html.BeginForm()) {
    @Html.ValidationMessageFor(m => m.Name)
    @Html.TextBoxFor(m => m.Name)

    @Html.Partial("_Attribute", Model.AttributeModel)

    <input type="submit" value="Click me" />
}

_Attribute.cshtml

@model Test.Models.AttributeModel

<h2>_Attribute</h2>

@Html.ValidationMessageFor(m => m.Size)
@Html.TextBoxFor(m => m.Size)

Controller

[HttpGet]
public ActionResult Create()
{
    ProductsModel model = new ProductsModel { AttributeModel = new AttributeModel() };
    return View(model);
}

[HttpPost]
public ActionResult Create(ProductsModel m)
{
    return View(m);
}

EDIT - SOLUTION

I found that the problem occurs because no input binds to AttributeModel which means that it will be null in ProductsModel, resulting in the follow errouneous statement:

@Html.Partial("_Attribute", null)

The solution is to use the HTML helper "EditorFor". Have a look at Complex models and partial views - model binding issue in ASP.NET MVC 3

Community
  • 1
  • 1
Peter
  • 505
  • 5
  • 12

3 Answers3

2

I suspect your problem is in your postback action. I would thing that the View that it is getting has AttributeModel as null so when you are calling the Partial you are actually calling it with ("_Attribute", null) and if the model is null then it will pass the current model in instead.

You need to make sure you have a valid AttributeModel on your ProductsModel.

Chris
  • 27,210
  • 6
  • 71
  • 92
  • Well thank you, that is indeed the problem! But the AttributeModel is always null it seems. Why does input not bind to that model in my partial view? – Peter May 15 '14 at 11:07
  • I'm not sure. The magic of model binding is not always something I fully understand. Perhaps a separate question for that might be in order. – Chris May 15 '14 at 11:10
1

You need to initialize the AttributeModel property of your class like

public class ProductsModel
{
   [Required]
   public string Name { get; set; }
   public AttributeModel AttributeModel { get; set; }
   public ProductsModel()
   {
     this.AttributeModel =new AttributeModel();
    }
}

Because initially AttributeModel property is set to null.

0

The Error is very descriptive.Its telling what is done wrong.

Your partial view requires object of type Test.Models.AttributeModel but you are passing object of type Test.Models.ProductsModel

Here you have set Model to Test.Models.AttributeModel

@model Test.Models.AttributeModel

<h2>_Attribute</h2>

@Html.ValidationMessageFor(m => m.Size)
@Html.TextBoxFor(m => m.Size)

Change you partial view Model to Test.Models.AttributeModel or pass object of type Test.Models.AttributeModel from the action.

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • But why? Does Model.AttributeModel not return Test.Models.AttributeModel? – Peter May 15 '14 at 10:26
  • if you show your action as well that will be more easy to help – Ehsan Sajjad May 15 '14 at 10:26
  • I have added it to my question. But the way I am doing it is obviously not the way to do it? – Peter May 15 '14 at 10:29
  • which one is for partial view? – Ehsan Sajjad May 15 '14 at 10:50
  • _Attribute.cshtml is the partial view – Peter May 15 '14 at 10:52
  • Well, the error first occur when i click the submit – Peter May 15 '14 at 10:59
  • Changing the model that the view uses is not the way to fix this problem. The @model shows what model is required so clearly the problem is with the partial's model declaration not matching the model passed in. – Chris May 15 '14 at 11:00
  • you need to pass whole mode like this: ``@Html.Partial("_Attribute",Model)`` – Ehsan Sajjad May 15 '14 at 11:02
  • @Peter: if the problem occurs only after you click (ie after the first postback) then that is vital information that should be edited into your question. – Chris May 15 '14 at 11:02
  • and in partial view change model to: ``@model Test.Models.ProductsModel`` – Ehsan Sajjad May 15 '14 at 11:02
  • @EhsanSajjad: That would then pass a ProductsModel into the partial which expects an AttributeModel – Chris May 15 '14 at 11:03
  • read the second comment, acually issue is that model is property of ProductsModel so its base type is ProductsModel and error will come surely – Ehsan Sajjad May 15 '14 at 11:03
  • You shouldn't need to change any of the `@model` statements though. The fix should be to ensure that the correct model is passed into the view in the first place, not blindly change things to hope they match. The question here is really why is a `ProductsModel` being passed into the partial when I think an `AttributesModel` should be getting passed. – Chris May 15 '14 at 11:07
  • yes that is little weird but what i suspect is as it is property of ProductModel so it is taking property's base type, – Ehsan Sajjad May 15 '14 at 11:09
  • Thank you guys. I have found a solution. It is updated in the question. I don't know if that is the practice, but it will probably be easier if someone else have the same question. – Peter May 15 '14 at 11:41
  • This answer is completely wrong. The correct object type was passed but it was uninitialized (i.e. null, so the parent object was passed instead)... -1 to reverse the obviously "mistaken" up-vote *you seem to get a lot of*. :) – iCollect.it Ltd May 20 '14 at 09:03