2009-07-18 9 views
34

Actualicé mi sitio para utilizar ASP.Net MVC desde los formularios web tradicionales de ASP.Net. Estoy usando el enrutamiento MVC para redirigir las peticiones de páginas .aspx de edad para su nuevo equivalente Controlador/Acción:¿Cómo enrutar imágenes usando el enrutamiento ASP.Net MVC?

 routes.MapRoute(
      "OldPage", 
      "oldpage.aspx", 
      new { controller = "NewController", action = "NewAction", id = "" } 
     ); 

Esto es trabajo grande de páginas, ya que se asignan directamente a un controlador y acción. Sin embargo, mi problema son las solicitudes de imágenes: no estoy seguro de cómo redireccionar esas solicitudes entrantes.

Necesito redirigir las solicitudes entrantes para http://www.domain.com/graphics/image.png a http://www.domain.com/content/images/image.png.

¿Cuál es la sintaxis correcta cuando se usa el método .MapRoute()?

Respuesta

48

No se puede hacer esto "de fábrica" ​​con el framework MVC. Recuerde que existe una diferencia entre enrutamiento y reescritura de URL. El enrutamiento es asignar cada solicitud a un recurso, y el recurso esperado es una pieza de código.

Sin embargo, la flexibilidad de la estructura MVC le permite hacer esto sin ningún problema real. De manera predeterminada, cuando llama al routes.MapRoute(), maneja la solicitud con una instancia de MvcRouteHandler(). Puede crear un controlador personalizado para manejar las URL de su imagen.

  1. crear una clase, tal vez llamada ImageRouteHandler, que implementa IRouteHandler.

  2. agregar la asignación a su aplicación como esta:

    routes.Add("ImagesRoute", new Route("graphics/{filename}",
    new ImageRouteHandler()));

  3. Eso es todo.

Esto es lo que tu clase IRouteHandler parece:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Web; 
using System.Web.Compilation; 
using System.Web.Routing; 
using System.Web.UI; 

namespace MvcApplication1 
{ 
    public class ImageRouteHandler : IRouteHandler 
    { 
     public IHttpHandler GetHttpHandler(RequestContext requestContext) 
     { 
      string filename = requestContext.RouteData.Values["filename"] as string; 

      if (string.IsNullOrEmpty(filename)) 
      { 
       // return a 404 HttpHandler here 
      } 
      else 
      { 
       requestContext.HttpContext.Response.Clear(); 
       requestContext.HttpContext.Response.ContentType = GetContentType(requestContext.HttpContext.Request.Url.ToString()); 

       // find physical path to image here. 
       string filepath = requestContext.HttpContext.Server.MapPath("~/test.jpg"); 

       requestContext.HttpContext.Response.WriteFile(filepath); 
       requestContext.HttpContext.Response.End(); 

      } 
      return null; 
     } 

     private static string GetContentType(String path) 
     { 
      switch (Path.GetExtension(path)) 
      { 
       case ".bmp": return "Image/bmp"; 
       case ".gif": return "Image/gif"; 
       case ".jpg": return "Image/jpeg"; 
       case ".png": return "Image/png"; 
       default: break; 
      } 
      return ""; 
     } 
    } 
} 
+0

wow, que funcionó a la perfección. ¡gracias! –

+0

no hay problema, me alegro de que haya ayudado. – womp

+0

¿Puede funcionar sin el método Response.End? Solo piense que lanzar una excepción (desde Response.End) en cada solicitud de imagen no es la mejor manera ... – Kamarey

6

Si se va a hacer esto usando ASP.NET Web Forms 3.5 SP1 tendría que crear un ImageHTTPHandler independiente que implementa IHttpHandler para manejar la respuesta . Esencialmente, todo lo que tendrías que hacer es poner el código que está actualmente en el método GetHttpHandler en el método ProcessRequest de tu ImageHttpHandler. También movería el método GetContentType a la clase ImageHTTPHandler. También agregue una variable para mantener el nombre del archivo.

Entonces su clase ImageRouteHanlder parece:

public class ImageRouteHandler:IRouteHandler 
    { 
     public IHttpHandler GetHttpHandler(RequestContext requestContext) 
     { 
      string filename = requestContext.RouteData.Values["filename"] as string; 

      return new ImageHttpHandler(filename); 

     } 
    } 

y clase ImageHttpHandler se vería así:

public class ImageHttpHandler:IHttpHandler 
    { 
     private string _fileName; 

     public ImageHttpHandler(string filename) 
     { 
      _fileName = filename; 
     } 

     #region IHttpHandler Members 

     public bool IsReusable 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public void ProcessRequest(HttpContext context) 
     { 
      if (string.IsNullOrEmpty(_fileName)) 
      { 
       context.Response.Clear(); 
       context.Response.StatusCode = 404; 
       context.Response.End(); 
      } 
      else 
      { 
       context.Response.Clear(); 
       context.Response.ContentType = GetContentType(context.Request.Url.ToString()); 

       // find physical path to image here. 
       string filepath = context.Server.MapPath("~/images/" + _fileName); 

       context.Response.WriteFile(filepath); 
       context.Response.End(); 
      } 

     } 

     private static string GetContentType(String path) 
     { 
      switch (Path.GetExtension(path)) 
      { 
       case ".bmp": return "Image/bmp"; 
       case ".gif": return "Image/gif"; 
       case ".jpg": return "Image/jpeg"; 
       case ".png": return "Image/png"; 
       default: break; 
      } 
      return ""; 
     } 

     #endregion 
    } 
Cuestiones relacionadas