I have written a List`1 editor template for use with the EditorFor extension methods (MVC2), however I am running into issues when using generics + null objects.
Given a model
class MyModel {
public Foo SomeFoo { get;set; }
public List<Foo> SomeFooList { get;set; }
}
and a template in /Views/Shared/EditorTemplates/List`1.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
IEnumerable enumerableModel;
if (Model != null && (enumerableModel = Model as IEnumerable) != null)
{
foreach (var v in enumerableModel)
{
var model = v;
Response.Write(Html.EditorFor(m => model));
}
}
%>
I get the expected editor for SomeFoo, and any elements of SomeFooList which are not null, as the type in ModelMetaData will be "Foo". However, if I have "null" as one of the objects in SomeFooList, I get nothing rendered as model is of type "object" and not Foo or more generically T from my list's generic arguments.
Essentially I would like to achieve something like
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<T>> where T : class" %>
so I know the types of my list.
I could also look at changing the ModelMetaData.ModelType field in the case of a null (by creating a new object, as this is readonly) -- but this is one of those nasty hacks I would like to avoid.
Another thought is calling the EditorFor method with .Invoke and passing typeof(T) into there, but again, I would like to avoid this type of code if possible.
Any thoughts?
Update:
Trying to get the type into model meta data was looking a little trickier than I first expected. I have updated my code with the following which seems to work, but I am still not too keen on the solition:
if (Model != null && (enumerableModel = Model as IEnumerable) != null)
{
Type listType = null;
if (enumerableModel.GetType().IsGenericType)
{
listType = enumerableModel.GetType().GetGenericArguments()[0];
}
foreach (var v in enumerableModel)
{
var model = v;
if (model == null && listType != null)
model = Activator.CreateInstance(listType);
Response.Write(Html.EditorFor(m => model));
}
}
Amar