How can I create a 'generic' control in Asp.Net MVC Razor?

Change the define in _Control.cshtml:

@model SimpleExample<dynamic> to @model dynamic.

It will work, but will lose the intellisense of SimpleExample, the intellisense of MyViewData will still work.

I think it's because the dynamic type will be known in runtime, but the type of generics

require an early time(maybe is compile time), at that point, only object is be known.


You could use a generic Object and then, using reflection, render the properties of this object (using an helper to list the properties). This is the same approach used by Twitter Bootstrap for MVC 4 (from wich part of this code has been copied, for convenience) : http://nuget.org/packages/twitter.bootstrap.mvc4

_Control.cshtml

@model Object
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>@Model.GetLabel()</legend>
        @foreach (var property in Model.VisibleProperties())
        {
            using(Html.ControlGroupFor(property.Name)){
                @Html.Label(property.Name)
                @Html.Editor(property.Name)
                @Html.ValidationMessage(property.Name, null)
            }
        }
        <button type="submit">Submit</button>
    </fieldset>
}

Helper.cs

public static string GetLabel(this PropertyInfo propertyInfo)
{
    var meta = ModelMetadataProviders.Current.GetMetadataForProperty(null, propertyInfo.DeclaringType, propertyInfo.Name);
    return meta.GetDisplayName();
}

public static PropertyInfo[] VisibleProperties(this IEnumerable Model)
{
    var elementType = Model.GetType().GetElementType();
    if (elementType == null)
    {
        elementType = Model.GetType().GetGenericArguments()[0];
    }
    return elementType.GetProperties().Where(info => info.Name != elementType.IdentifierPropertyName()).ToArray();
}

public static PropertyInfo[] VisibleProperties(this Object model)
{
    return model.GetType().GetProperties().Where(info => info.Name != model.IdentifierPropertyName()).ToArray();
}