2010-11-12 11 views
7

Estoy creando una aplicación MVC que actualmente usa EditorFor para gennerar una gran cantidad de vistas. La vista completa es básicamente solo un Editor de modelo, y funciona muy bien. Sin embargo, he llegado a un pequeño problema, que parece que no puedo encontrar una solución, y es importante que funcione de la manera que lo necesito, y eso es cuando intento renderizar Editor para una interfaz. Las encuadernaciones y todo eso se ha solucionado, pero el problema es que el EditorFor ve que se trata de una interfaz, y se predetermina a la plantilla "Objeto". Necesito que mire la interfaz y vea si puede encontrar una plantilla con ese nombre, y si no puede, necesito que mire a través de todas las interfaces presentes para ver si coincide con cualquiera de ellas. Para explicarlo más sencillamente vistazo a este ejemplo:Reemplazando la selección predeterminada de la plantilla EditorFor en ASP.NET MVC 3 RC

interfaces:

public interface IAppProvider 
{ 
    string Name { get; set; } 
} 

public interface IAppMusicProvider : IAppProvider 
{ 
    int GetPlaylistCount(); 
} // Yeah, I know, this interface is not smart, but it's only for show. 

Si ahora crear una vista con el modelo = "IAppMusicProvider", y corro Html.EditorForModel(), lo necesito para encontrar el "~ Vistas \ Shared \ EditorTemplates \ IAppProvider.cshtml "-template. ¿Hay alguna manera simple de lograr esto?

Respuesta

1

¿Intentó utilizar el atributo [TemplateHint]?

+0

Sí, que funciona, pero no es una forma de evitar el problema (o más bien utilizado el atributo '[DataType]' en realidad). La aplicación que estoy creando va a ejecutar complementos, y necesito que funcione solo configurando la interfaz y sin tener que forzar a todos los desarrolladores de complementos al usuario '[DataType (" IAppProvider ")]'. – Alxandr

+0

Intente nombrar la plantilla de la misma manera que la interfaz? Si recuerdo esas son las únicas dos opciones. – jfar

+0

Eso tampoco funcionará, porque la plantilla debe funcionar para todos los 'IAppProvider's. Estoy buscando alguna forma de anular este comportamiento predeterminado, de modo que si proporciono una interfaz IAppProvider-implementation, usará IAppProvider-template. Es probable que esto deba codificarse en algún lugar de MVC (algún componente que deba modificarse, como se puede hacer con ControllerFactory, etc.), pero ni siquiera sé por dónde empezar. – Alxandr

1

Puede intentar cambiar ModelMetadata.TemplateHint en el ModelMetadataProvider. Una forma de hacerlo es con el patrón decorador:

public class AbstractTypeTemplateSupportingModelMetadataProvider : ModelMetadataProvider 
{ 
    private readonly ModelMetadataProvider wrapped; 

    public AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProvider wrapped) 
    { 
     this.wrapped = wrapped; 
    } 

    public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType) 
    { 
     var result = this.wrapped.GetMetadataForProperties(container, containerType).ToList(); 
     result.ForEach(ChangeTemplateHint); 

     return result; 
    } 

    public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName) 
    { 
     var result = this.wrapped.GetMetadataForProperty(modelAccessor, containerType, propertyName); 
     ChangeTemplateHint(result); 

     return result; 
    } 

    public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType) 
    { 
     var result = this.wrapped.GetMetadataForType(modelAccessor, modelType); 
     ChangeTemplateHint(result); 

     return result; 
    } 

    private void ChangeTemplateHint(ModelMetadata source) 
    { 
     if (source.Model is IAppProvider) //Or use source.ModelType if you want to support the model being null. 
      source.TemplateHint = typeof(IAppProvider).Name; 
    } 
} 

Y en su puesta en marcha lógica:

ModelMetadataProviders.Current = new AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProviders.Current); 
Cuestiones relacionadas