vista tutorial tag net mvc modelo form ejemplo desde controlador conceptos cero asp aprender c# asp.net-mvc plugins

tutorial - mvc c# windows forms ejemplo



Vistas en ensamblajes separados en ASP.NET MVC (4)

Intento crear una aplicación web en la que desee poder instalar ensamblajes por separado. Estoy usando MVC preview 4 combinado con Unity para la inyección de dependencias, que utilizo para crear los controladores de mis ensamblajes de complementos. Estoy usando WebForms (aspx por defecto) como mi motor de visualización.

Si quiero usar una vista, estoy atascado en los que están definidos en el proyecto central, debido a la compilación dinámica de la parte ASPX. Estoy buscando una forma adecuada de adjuntar archivos ASPX en un ensamblaje diferente, sin tener que pasar por todo el paso de implementación. ¿Me estoy perdiendo algo obvio? ¿O debería recurrir a la creación de mis puntos de vista mediante programación?

Actualización: cambié la respuesta aceptada. Aunque la respuesta de Dale es muy completa, busqué la solución con un proveedor de ruta virtual diferente. Funciona como un amuleto, y toma solo unas 20 líneas en código, creo.



Me tomó demasiado tiempo lograr que esto funcionara correctamente desde varias muestras parciales, así que aquí está el código completo necesario para obtener vistas desde una carpeta Vistas en una biblioteca compartida estructurada de la misma manera que una carpeta Vistas normal pero con todo configurado para compilar como incrustado recursos. Solo usará el archivo incrustado si el archivo habitual no existe.

La primera línea de Application_Start:

HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedViewPathProvider());

VirtualPathProvider

public class EmbeddedVirtualFile : VirtualFile { public EmbeddedVirtualFile(string virtualPath) : base(virtualPath) { } internal static string GetResourceName(string virtualPath) { if (!virtualPath.Contains("/Views/")) { return null; } var resourcename = virtualPath .Substring(virtualPath.IndexOf("Views/")) .Replace("Views/", "OrangeGuava.Common.Views.") .Replace("/", "."); return resourcename; } public override Stream Open() { Assembly assembly = Assembly.GetExecutingAssembly(); var resourcename = GetResourceName(this.VirtualPath); return assembly.GetManifestResourceStream(resourcename); } } public class EmbeddedViewPathProvider : VirtualPathProvider { private bool ResourceFileExists(string virtualPath) { Assembly assembly = Assembly.GetExecutingAssembly(); var resourcename = EmbeddedVirtualFile.GetResourceName(virtualPath); var result = resourcename != null && assembly.GetManifestResourceNames().Contains(resourcename); return result; } public override bool FileExists(string virtualPath) { return base.FileExists(virtualPath) || ResourceFileExists(virtualPath); } public override VirtualFile GetFile(string virtualPath) { if (!base.FileExists(virtualPath)) { return new EmbeddedVirtualFile(virtualPath); } else { return base.GetFile(virtualPath); } } }

El último paso para que funcione es que la raíz Web.Config debe contener las configuraciones correctas para analizar las vistas MVC fuertemente tipadas, ya que no se usará la de la carpeta de vistas:

<pages validateRequest="false" pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <controls> <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" /> </controls> </pages>

Se requieren algunos pasos adicionales para que funcione con Mono. En primer lugar, debe implementar GetDirectory, ya que todos los archivos en la carpeta de vistas se cargan cuando se inicia la aplicación en lugar de según sea necesario:

public override VirtualDirectory GetDirectory(string virtualDir) { Log.LogInfo("GetDirectory - " + virtualDir); var b = base.GetDirectory(virtualDir); return new EmbeddedVirtualDirectory(virtualDir, b); } public class EmbeddedVirtualDirectory : VirtualDirectory { private VirtualDirectory FileDir { get; set; } public EmbeddedVirtualDirectory(string virtualPath, VirtualDirectory filedir) : base(virtualPath) { FileDir = filedir; } public override System.Collections.IEnumerable Children { get { return FileDir.Children; } } public override System.Collections.IEnumerable Directories { get { return FileDir.Directories; } } public override System.Collections.IEnumerable Files { get { if (!VirtualPath.Contains("/Views/") || VirtualPath.EndsWith("/Views/")) { return FileDir.Files; } var fl = new List<VirtualFile>(); foreach (VirtualFile f in FileDir.Files) { fl.Add(f); } var resourcename = VirtualPath.Substring(VirtualPath.IndexOf("Views/")) .Replace("Views/", "OrangeGuava.Common.Views.") .Replace("/", "."); Assembly assembly = Assembly.GetExecutingAssembly(); var rfl = assembly.GetManifestResourceNames() .Where(s => s.StartsWith(resourcename)) .Select(s => VirtualPath + s.Replace(resourcename, "")) .Select(s => new EmbeddedVirtualFile(s)); fl.AddRange(rfl); return fl; } } }

Finalmente, las vistas fuertemente tipadas casi funcionarán perfectamente. El modelo se tratará como un objeto sin tipo, por lo que para obtener una escritura fuerte, debe comenzar sus vistas compartidas con algo como

<% var Model2 = Model as IEnumerable<AppModel>; %>


Una adición a todos ustedes que todavía están buscando el santo grial: me he acercado un poco más a encontrarlo, si no están demasiado apegados al motor de visualización de formularios web.

Recientemente probé Spark viewengine. Además de ser totalmente increíble y no volvería a los formularios web, incluso si me amenazaban, también proporciona algunos ganchos muy buenos para la modularidad de una aplicación. El ejemplo en sus documentos está usando Windsor como un contenedor IoC, pero no puedo imaginar que sea mucho más difícil si quieres tomar otro enfoque.


protected void Application_Start() { WebFormViewEngine engine = new WebFormViewEngine(); engine.ViewLocationFormats = new[] { "~/bin/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" }; engine.PartialViewLocationFormats = engine.ViewLocationFormats; ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(engine); RegisterRoutes(RouteTable.Routes); }

Establezca la propiedad ''Copiar en la salida'' de su vista en ''Copiar siempre''