views:

2137

answers:

3

If i got view which inherits from:

System.Web.Mvc.ViewPage<Foo>

Where Foo has a property Bar with a type string
And view wants to render strongly typed partial view which inherits from:

System.Web.Mvc.ViewUserControl<string>

like this:

Html.RenderPartial("_Bar", Model.Bar);%>

Then why it will throw this:

The model item passed into the dictionary is of type 'Foo'
but this dictionary requires a model item of type 'System.String'.

when bar is not initialized?

More specific: why it passes Foo, where it should pass null?

+2  A: 

If you pass null as the model to RenderPartial, then it will look at the original model, which is why the error says foo.

You'll need to make sure that bar is initialized to be an empty string instead of null.

Edit: @Arnis, look at the source code. It doesn't lie. You are passing null to the overload of RenderPartial. You are not passing Foo. Internally, the system uses the Model from your page's ViewContext (which is Foo) when you pass a null Bar to RenderPartial.

Dennis Palmer
This answer seems wrong to me. Question was: "why it passes Foo, where it should pass null?" and not "Does it passes Foo instead of null?".
Arnis L.
@Dennis sure it does not lie, but it does not answer to question WHY it needs that. tvanfosson named the reason. Thanks anyway. :)
Arnis L.
+4  A: 

Look at ASP.NET MVC source (HtmlHelper.cs -> RenderPartialInternal method -> line 258):

...

if (model == null) {
    if (viewData == null) {
        newViewData = new ViewDataDictionary(ViewData);
    }

...

this is exactly your case. ASP.NET MVC uses the ViewData from your ViewContext

UPDATED:

Try this instead:

<% Html.RenderPartial("_Bar", Model.Bar ?? "Default" ); %>
eu-ge-ne
+1 for "Look at ASP.NET MVC source" http://aspnet.codeplex.com/sourcecontrol/changeset/view/23011?projectName=aspnet#266468 Taking a look at RenderPartialExtensions.cs will also help. http://aspnet.codeplex.com/sourcecontrol/changeset/view/23011?projectName=aspnet#288013
Dennis Palmer
Sorry, eu-ge-ne, but i can't accept your answer either. See comment at Dennis post for details. :)
Arnis L.
+7  A: 

As @Dennis points out, if the model value is null, it will use the existing model from the view. The reason for this is to support the ability to call a partial view using a signature that contains only the partial view name and have it reuse the existing model. Internally, all of the RenderPartial helpers defer to a single RenderPartialInternal method. The way you get that method to reuse the existing model is to pass in a null value for the model (which the signature that takes only a view name does). When you pass a null value to the signature containing both a view name and a model object, you are essentially replicating the behavior of the method that takes only the view name.

This should fix your issue:

<% Html.RenderPartial( "_Bar", Model.Bar ?? string.Empty ) %>
tvanfosson
+1 for a better explanation of the concept.
Dennis Palmer