views:

108

answers:

1

I have a partial view that inherits from ViewUserControl<Guid?> - i.e. it's model is of type Nullable<Guid>. Very simple view, nothing special, but that's not the point.

Somewhere else, I do Html.RenderPartial( "MyView", someGuid ), where someGuid is of type Nullable<Guid>. Everything's perfectly legal, should work OK, right?

But here's the gotcha: the second argument of Html.RenderPartial is of type object, and therefore, Nullable<Guid> being a value type, it must be boxed. But nullable types are somehow special in the CLR, so that when you box one of those, you actually get either a boxed value of type T (Nullable's argument), or a null if the nullable didn't have a value to begin with. And that last case is actually interesting.

Turns out, sometimes, I do have a situation when someGuid.HasValue == false. And in those cases, I effectively get a call Html.RenderPartial( "MyView", null ). And what does the HtmlHelper do when the model is null? Believe it or not, it just goes ahead and takes the parent view's model. Regardless of it's type.

So, naturally, in those cases, I get an exception saying: "The model item passed into the dictionary is of type 'Parent.View.Model.Type', but this dictionary requires a model item of type 'System.Guid?'"

So the question is: how do I make MVC correctly pass new Nullable<Guid> { HasValue = false } instead of trying to grab the parent's model?

Note: I did consider wrapping my Guid? in an object of another type, specifically created for this occasion, but this seems completely ridiculous. Don't want to do that as long as there's another way.

Note 2: now that I've wrote all this, I've realized that the question may be reduced to how to pass a null for model without ending up with parent's model?

+2  A: 
<% Html.RenderPartial("MyView", someGuid ?? new Guid()); %>

UPDATE:

Using editor and/or display templates in ASP.NET MVC 2.0 you can achieve the desired result. Place a Guid.ascx file in the Shared/EditorTemplates folder and include it like this:

<%= Html.EditorFor(x => someGuid) %>

or if the guid is a property of the main model:

<%= Html.EditorFor(x => x.SomeGuid) %>

Now if you put a <%= Model.HasValue %> inside the partial you can get false but not with RenderPartial.

Darin Dimitrov
But that will give me an empty GUID instead of null, wouldn't it?
Fyodor Soikin
Yes, it will. Using `RenderPartial` you cannot achieve this effect.
Darin Dimitrov
Regarding your update: I don't see any HtmlHelper's extension methods with an "Editor" word in them which would take a lambda. Did you make a typo of some sort? (and yes, I'm using MVC 2.0; have VS2010 installed)
Fyodor Soikin
Oh, there is such a method. See this article: http://weblogs.asp.net/rashid/archive/2009/11/27/extending-asp-net-mvc-2-templates.aspx Try creating a new ASP.NET MVC 2.0 project and there you will find the EditorFor method.
Darin Dimitrov
That article only mentions `EditorForModel` method, which I do see. But it doesn't take lambda or delegate. And I have created my project only a couple of days ago, and it's almost virgin at this point.
Fyodor Soikin
I have no idea why you are not seeing this method but it definitely exists. Maybe a bug in the Intellisense? Here's another article: http://lsd.luminis.nl/asp-net-mvc-editor-templates/ And on MSDN: http://msdn.microsoft.com/en-us/library/ee834942(v=VS.100).aspx
Darin Dimitrov
Ok, I found it finally. It extends templated `HtmlHelper<T>`, while I was trying to call it on non-templated `HtmlHelper`. And it works now. Thanks!
Fyodor Soikin
@Fyodor, glad to hear you made it work.
Darin Dimitrov