2011-01-19 12 views
12

¿Es cierto que es posible cargar Vista desde cualquier lugar sin la implementación de VirtualPathProvider personalizada en MVC 3.0?ASP.NET MVC 3.0 Razor, carga la vista desde cualquier lugar fuera de la caja?

Si es cierto cómo hacerlo?

Básicamente no es un problema para poner en práctica la costumbre VirtualPathProvider que cargar el Vista desde cualquier lugar, pero mi aplicación trabaja sólo en MVC 2.0 y no funciona facturan con MVC 3.0, primer plano algún método razón GetFile nuevo llamado de puntos de vista no existía en MVC 3.0 y en ese caso me estoy haciendo "Server Error in '/' Application."

he seguido el mismo código para mi costumbre VirtualPathProvider desde aquí: http://buildstarted.com/2010/09/28/mvc-3-razor-view-engine-without-a-controller/

ACTUALIZA 1

OK ID Identificación solucionar mi problema con mi costumbre VirtualPathProvider después de poner el registro de mi costumbre VirtualPathProvider proveedor de primera línea en el Application_Start()

protected void Application_Start() 
    { 
     //Should be first line before routes and areas registration. 
     HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider()); 

     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 
    } 

Cuando el registro de VirtualPathProvider costumbre en Global.asax.cs folowing después AreaRegistration.RegisterAllAreas(); o RegisterRoutes(RouteTable.Routes); método método override VirtualFile GetFile(string virtualPath) no trabajará para " Vistas virtuales ".

ACTUALIZACIÓN 2

lo hace significa que las clases RazorViewRazorViewEngineRender y es la respuesta?

ACTUALIZACIÓN 3

Si tengo representación de cadena de mi punto de vista de afeitar que no existe en el sistema de archivos (por ejemplo, almaceno vistas de afeitar en la base de datos) ¿En qué puedo hacer que el uso de este tipo de enfoque http://buildstarted.com/2010/09/28/mvc-3-razor-view-engine-without-a-controller/

Por ejemplo

representación de cadena de mi punto de vista se parece a esto:

"@{ 
    ViewBag.Title = ""About Us""; 
} 

<h2>About</h2> 
<p> 
    Put content here. 
</p>" 

ACTUALIZACIÓN 4

ahora veo, para poder usar @Html.<something> se debe implementar TemplateBase personalizado. La muestra de implementación de HtmlTemplateBase<T> se puede encontrar aquí http://www.fidelitydesign.net/?p=239, pero no funcionará con RazorEngine v2, estoy obteniendo la plantilla compilada satisfactoriamente, y luego de que el método public override void Execute() cargado en el ensamblado no se ejecute, recibo un error: El método o operación no se lleva a cabo (StackTrace: http://tinypic.com/r/dcow4/7)

para hacer “public override T Modelo” sucedió lo hice declaración de cambio de “modelo público TModel” a “público TModel modelo virtual” en “TemplateBase clase abstracta pública: TemplateBase, ITemplate” . ¿Puede haber algún otro cambio que deba hacerse? ¿O algo en HtmlTemplateBase<T> debería hacerse de otra manera?

+0

También, busque en http://stackoverflow.com/questions/3367106/pulling-a-view-from-a-database-rather-than-a-file – Buildstarted

Respuesta

2

No, cargar una vista desde la base de datos no es compatible por defecto. Necesita escribir su propio VirtualPathProvider.

Tenga en cuenta que la publicación del blog de Ben en realidad no aborda directamente el problema que está tratando de resolver. La siguiente publicación de blog se parece mucho más a lo que desea: http://rebuildall.umbraworks.net/2009/11/17/ASP_NET_MVC_and_virtual_views.Tenga en cuenta que no importa si está intentando almacenar vistas de razor o aspx en la base de datos. Los proveedores de rutas virtuales en Asp.Net simplemente tratan sobre mapear una ruta a una secuencia de bytes que son los contenidos del archivo representado por esa ruta.

+0

Ok, pero si leyó mi pregunta hasta el final describí algunos detalles/problemas que mi proveedor no trabajará con MVC 3.0. – Kuncevic

+0

@bigb ver actualización – marcind

6

No se deje confundir por el código de muestra de Ben (@BuildStarted) en su artículo. Él detalla cómo usar una versión temprana de Razor ViewEngine para representar plantillas sin usar una acción de controlador. La intención era poder hacer plantillas de forma genérica, en lugar de vistas de páginas específicas. (Esto es lo que ha evolucionado en nuestro framework de plantillas RazorEngine @http://razorengine.codeplex.com).

El VirtualPathProvider sigue siendo una parte central de ASP.NET. Parece haber una confusión general acerca de que el DependencyResolver de MVC 3 sea un reemplazo de un VirtualPathProvider, pero este no es el caso, aún necesita que un proveedor tenga acceso a contenido en una ruta virtual (que, por cierto, todas las rutas en ASP.NET son virtual).

Al revertir mi respuesta original, debe poder lograr lo que desea puramente mediante la subclasificación del RazorViewEngine y usarlo para crear sus vistas.

Tener un vistazo a este tema: http://coderjournal.com/2009/05/creating-your-first-mvc-viewengine/

2

me encontré con un problema similar para la implementación de un VirtualPathProvider vistas de recursos incrustados. La solución fue implementar GetFolder y GetFile. El motor de vista no solo llama a GetFile cuando solicita esa vista. En la primera solicitud, busca en la carpeta de vistas todas las vistas disponibles. Si esa llamada no incluye las vistas de su base de datos en la lista, no se encontrarán cuando intente cargarlas.

1

Todos son correctos. Mi publicación no fue cómo cargar Razor como reemplazo sino como una forma de llamar a la afeitadora sin usar MVC. Ahora ... lo que desea es lo más probable relacionado con mi publicación aquí How to Download Razor View Engine Donde muestro cómo crear su propio ViewEngine para alojar una página de afeitar. Utiliza el mismo motor @Matthew Abbott y yo uso para RazorEngine, que puede obtener de CodePlex. Desafortunadamente no está completo, pero debería darle una idea de cómo hacerlo. (Voy a publicar aquí también)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Hosting; 
using System.IO; 
using System.Text.RegularExpressions; 
using System.Xml.Linq; 

namespace RazorViewEngine { 
    /// <summary> 
    /// ViewEngine for the RazorView. Provides basic file handling to load views. 
    /// </summary> 
    public class RazorViewEngine : IViewEngine { 

     string[] SearchLocations { get; set; } 
     Tuple<string, string, RazorView> Cache { get; set; } 
     VirtualPathProvider VirtualPathProvider { get; set; } 

     public RazorViewEngine() { 
      //{1} == Controller name 
      //{0} == View name 
      SearchLocations = new string[] { 
       "~/Views/{1}/{0}.cshtml", 
       "~/Views/Shared/{0}.cshtml", 
      }; 

      VirtualPathProvider = HostingEnvironment.VirtualPathProvider; 
     } 

     #region IViewEngine Members 

     public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { 
      return CreateView(controllerContext, partialViewName, null, null, useCache); 
     } 

     public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { 
      return CreateView(controllerContext, viewName, masterName, GetLayoutPath(controllerContext), useCache); 
     } 

     /// <summary> 
     /// Meat of the FindView methods. 
     /// </summary> 
     /// <param name="controllerContext">The current controller context for this request.</param> 
     /// <param name="viewName">The requested view name. </param> 
     /// <param name="masterName">The master page view name (currently unused)</param> 
     /// <param name="layoutPath">The layout path location (Replaces the masterpage in other view engines)</param> 
     /// <param name="useCache">Cache the viewpage?</param> 
     /// <remarks>The layout path is currently hardcoded to "Layout" and will look in the SearchLocations for that path</remarks> 
     /// <returns>Returns a ViewEngineResult with the requested view</returns> 
     public ViewEngineResult CreateView(ControllerContext controllerContext, string viewName, string masterName, string layoutPath, bool useCache) { 
      //grab the current controller from the route data 
      string controllerName = controllerContext.RouteData.GetRequiredString("controller"); 

      //for proper error handling we need to return a list of locations we attempted to search for the view 
      string[] SearchedLocations; 

      //get the actual path of the view - returns null if none is found 
      string viewPath = GetViewPath(viewName, controllerName, out SearchedLocations); 

      if (viewPath != null) { 
       RazorView view = new RazorView(this, controllerContext, viewPath, layoutPath); 
       return new ViewEngineResult(view, this); 
      } 

      //we couldn't find the view - return an array of all locations we've looked in 
      return new ViewEngineResult(SearchedLocations); 
     } 

     /// <summary> 
     /// Look for the view in the current file system 
     /// </summary> 
     /// <param name="viewName">The name of the View you're looking for</param> 
     /// <param name="controllerName">Current controller name</param> 
     /// <param name="SearchedLocations">out a list of locations searched</param> 
     /// <returns>A string value of the relative path</returns> 
     public string GetViewPath(string viewName, string controllerName, out string[] SearchedLocations) { 
      return FindPath(viewName, controllerName, out SearchedLocations); 
     } 

     /// <summary> 
     /// Look for the view in the current file system 
     /// </summary> 
     /// <param name="viewName">The name of the View you're looking for</param> 
     /// <param name="controllerName">Current controller name</param> 
     /// <param name="SearchedLocations">out a list of locations searched</param> 
     /// <returns>A string value of the relative path</returns> 
     public string FindPath(string viewName, string controllerName, out string[] SearchedLocations) { 
      SearchedLocations = new string[SearchLocations.Length]; 

      for (int i = 0; i < SearchLocations.Length; i++) { 
       string virtualPath = string.Format(SearchLocations[i], viewName, controllerName); 

       SearchedLocations[i] = virtualPath; 

       //check the active VirtualPathProvider if the file exists 
       if (VirtualPathProvider.FileExists(virtualPath)) { 
        //add it to cache - not currently implemented 
        return VirtualPathProvider.GetFile(virtualPath).VirtualPath; 
       } 
      } 

      return null; 
     } 

     /// <summary> 
     /// Get the layout virtual path 
     /// </summary> 
     /// <param name="controllerContext">The current Controller context for this request</param> 
     /// <returns>A string virtual path</returns> 
     public string GetLayoutPath(ControllerContext controllerContext) { 
      //This should probably be added to a list of locations - I'm not sure exactly 
      //what I need to do with this yet. 
      string[] locations; 

      return FindPath("Layout", controllerContext.RouteData.GetRequiredString("controller"), out locations); 
     } 

     /// <summary> 
     /// Current irrelevant 
     /// </summary> 
     /// <param name="controllerContext">The active controller context</param> 
     /// <param name="view">View to release</param> 
     public void ReleaseView(ControllerContext controllerContext, IView view) { 
      IDisposable disposable = view as IDisposable; 
      if (disposable != null) { 
       disposable.Dispose(); 
      } 
     } 

     #endregion 
    } 

    /// <summary> 
    /// Implements IView and renders a Razor 
    /// </summary> 
    public class RazorView : IView { 

     ControllerContext ControllerContext; 
     string ViewPath; 
     string LayoutPath; 
     RazorViewEngine Engine; 

     public RazorView(RazorViewEngine engine, ControllerContext controllerContext, string viewPath, string layoutPath) { 
      //load the file 
      this.ControllerContext = controllerContext; 
      this.ViewPath = viewPath; 
      this.LayoutPath = layoutPath; 
      this.Engine = engine; 
     } 

     #region IView Members 

     /// <summary> 
     /// Converts Razor to html and writes it to the passed in writer 
     /// </summary> 
     /// <param name="viewContext"></param> 
     /// <param name="writer"></param> 
     public void Render(ViewContext viewContext, System.IO.TextWriter writer) { 
      //View contents 
      string contents = new StreamReader(VirtualPathProvider.OpenFile(ViewPath)).ReadToEnd(); 
      string layoutContents = LayoutPath == null 
       ? null 
       : new StreamReader(VirtualPathProvider.OpenFile(LayoutPath)).ReadToEnd(); 

      contents = Parse(contents); 

      string output; 
      output = contents; 

      writer.Write(output); 
     } 

     /// <summary> 
     /// Converts Razor to html 
     /// </summary> 
     /// <param name="Razor">Razor text</param> 
     /// <returns>Html formatted Razor text</returns> 
     string Parse(string Razor) { 

      //Where do I get the model From 

      return RazorEngine.Razor.Parse(Razor); 
     } 

     #endregion 
    } 

} 
+0

@BuildStarted Lectura actualizada @Matthew Abbott respuesta, pensé que iba a necesitar hacer algo así, gracias por todos los detalles. – Kuncevic

+0

Lo primero que hice fue agregar el motor personalizado (su implementación) como está, luego de ejecutar mi aplicación web MVC 3.0 me sale un error. No puedo compilar la plantilla. Verifique la lista de Errores para más detalles. Luego descubrí que no estoy usando una versión actualizada de RazorEngine y luego de descargar v 2.0 recibo el mismo error. También leí este hilo http://razorengine.codeplex.com/Thread/View.aspx?ThreadId=235751, tengo Microsoft.CSharp y System.Core a los que se hace referencia en mi aplicación y también System.Web.Razor.dll establecí verdadero para copiar local. La plantilla que no se compilará es simplemente MVC3.0 Home/Index View por defecto. – Kuncevic

+0

Que me refiero a RazorEngine como un proyecto para entrar ... aquí está printcrin con más detalles acerca de un error http://tinypic.com/r/rlx8cj/7, y también encontré este error en los resultados.Errors: CompiledAssembly = 'results.CompiledAssembly' lanzó una excepción de tipo 'System.IO.FileNotFoundException' ¿Está de alguna manera conectado con plena confianza? – Kuncevic

Cuestiones relacionadas