3

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

1 Answer 1

1

Maybe you could think about creating a custom structure similar to Nullable<T> to contain your entity? Nullable<T> contrains T to be a struct which is why you'd have to create your own one. That way you can check a HasValue property rather than having the problem with checking null and not knowing the type.

Sign up to request clarification or add additional context in comments.

3 Comments

By the way, if some could show me how to write Nullable< T > properly in this markdown without having to put in spaces, I'd be greatful!
Wrap it inside backticks (`) and you get Nullable<T>.
That seems fair, I will have a play with this tomorrow and see if I can get anything from it. Cheers

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.