47
@model Customer

@Html.Partial("_UserProfile", (UserProfile)Model.UserProfile)

When i run this code, i get this error:

The model item passed into the dictionary is of type 'Customer', but this dictionary requires a model item of type 'UserProfile'.

Partial View _UserProfile is strongly typed.

I want to be able to edit these field. Any suggestions?

tereško
  • 58,060
  • 25
  • 98
  • 150
Rasmus-E
  • 832
  • 1
  • 8
  • 15
  • also check the difference between Html.Action and Html.Partial is useful https://stackoverflow.com/questions/16886585/html-partial-skips-the-controller-action – Iman Dec 06 '17 at 15:47

7 Answers7

108

Make sure your Model.UserProfile is not null.

I found your post trying to debug the same error, and it turned out I hadn't initialised my "Model.UserProfile" equivalent.

I guess what's happening here, is that if a null model is passed to RenderPartial, it defaults to using the main view's model? Can anyone confirm this?

SharpC
  • 6,974
  • 4
  • 45
  • 40
Murray
  • 1,948
  • 1
  • 12
  • 18
  • 21
    You're right. This is an overloading issue. When you try to call `@Html.Partial(,)` while passing the Model as `null`, the implementation will assume you have called the method version that accepts the name of the view only and passes the current view model to the partial view. – Lafi Mar 11 '14 at 11:40
  • Yes, you are correct! You can add PropertyThatWasNull = new YourObject() in your ViewModel Constructor to correct this in most cases. Might be more difficult with a null UserProfile object. – jwize Oct 23 '14 at 21:14
  • 1
    Nasty bug on MVC, just been hit by the by it too, thanks for the tip. – Alejandro Apr 17 '15 at 18:47
  • I have created some helpers for this problem in MVC 3: https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs The code probably doesn't work anymore, but the concepts should be reusable. – Jaap May 15 '19 at 13:08
22

If Model.UserProfile is null, it will attempt to pass in your customer model.

Two ways to get around this:

@model Customer

@Html.Partial("_UserProfile", (UserProfile)Model.UserProfile, new ViewDataDictionary())

Or:

@model Customer

if (Model.UserProfile != null)
{
   @Html.Partial("_UserProfile", (UserProfile)Model.UserProfile)
}
Kcoder
  • 3,422
  • 4
  • 37
  • 56
  • The second wouldn't work, you'd need to use a defensive cast: `@Html.Partial("_UserProfile", Model as UserProfile)` – Echilon Aug 09 '16 at 14:59
  • @Echilon: You are right the second doesn't work, but neither does your suggestion. The first option in the answer does resolve the issue though. – musefan Jan 13 '17 at 16:14
  • The second one is designed to skip the partial view if the model is null. In this example, it may not be useful to display a UserProfile view when there's no user profile and this will avoid the error. – Kcoder Jan 14 '17 at 19:48
2

I have faced the same problem but finally I had figured it out. There is a type mismatch in passed models .. Your View accepts model of type Customer but you partial view is passing the model Userprofile so what you have to do is pass the same model in both or.... create a model that have all properties of both models. Surely your problem will be solved.

Dashanan
  • 122
  • 3
  • 16
1

I ran into this problem when dealing with parts of a user profile such as Name and Address records. If the user had an incomplete profile I want the account management view to detect a null Address record and display an Action link to create a new Address or display whatever address data is available.

As described by others when null is passed the overload for Html.RenderPartial gets triggered and the parent View Model is passed through. I ended up converting my partial views to Display and Editor Templates to get around it. Here are some How-To articles from: Hansleman and codeguru

You get better re-usability from this method and it preserves the null values: In your View:

@Html.DisplayFor( m=> m.Address)

Then handle the null value in the DisplayTemplate.

@model Namespace.Models.MyObject
...
if(@Model != null){
...
}else{
...
}
  • 1
    Of all the methods we tried to solve our own version of this problem, this was by far the best. ViewData and ModelState (including ModelState errors etc.) are all passed normally with this. Most of the other solutions pass a new ViewData object which screws up any ModelState. – mikeschuld Aug 29 '16 at 19:18
  • Exactly @mikeschuld Why would you want to squash error handling and cast a new object when in fact your model is null? Just handle the state where it should be handled. In fairness I didn't answer the question which was how to use Html.Partial I just said don't use it if your object could be null. – reachingnexus Sep 30 '16 at 13:44
0

It will fallback on initial model if passed item is null.

Try this:

@Html.Partial("_UserProfile", (UserProfile)Model.UserProfile ?? new UserProfile())
annemartijn
  • 1,538
  • 1
  • 23
  • 45
-1

Your trying to case a Customer type object to a UserProfile type object. By default this wont work as the framework has no idea how to cast these objects. If you absolutely must do it this way the only option is to provide explicit cast operator like:

public static explicit operator Digit(byte b)  // explicit byte to digit conversion operator
{
    Digit d = new Digit(b);  // explicit conversion

    System.Console.WriteLine("Conversion occurred.");
    return d;
}

You can read more about it here.

Jammer
  • 9,969
  • 11
  • 68
  • 115
  • There is a cast for the property UserProfile. In this case I think it should be unnecessary but it looks like an explicit attempt to tell the compiler this is the type I am passing in. – Observer Apr 03 '16 at 13:38
-1

Add the keyword "virtual" to the UserProfile property on the Customer model. It is the easyest way overcome the lazy loading, but performance..

roni
  • 51
  • 7