2010-02-01 81 views
5

Tengo una aplicación ASP.NET MVC donde estoy mostrando imágenes.ASP.NET MVC URL de imagen generadas dinámicamente

Estas imágenes pueden estar ubicadas en el sistema de archivos o dentro de una base de datos. Esto está bien ya que puedo usar Url.Action en mi imagen, llamar la acción en mi controlador y devolver la imagen desde la ubicación correspondiente.

Sin embargo, quiero ser compatible con las imágenes almacenadas en Amazon S3. En este caso, no quiero que la acción de mi controlador devuelva la imagen, sino que debería generar una URL de imagen para Amazon S3.

Aunque podría realizar esta lógica dentro de mi vista, p.

<% si (Model.Images [0] == .ImageLocation ImageLocation.AmazonS3) {%> // genera la imagen Amazon

que necesito para asegurar que la imagen existe en primer lugar.

Esencialmente necesito pasar un valor de tamaño a mi controlador para que pueda verificar que la imagen exista en ese tamaño (ya sea en la base de datos, sistema de archivos o amazon s3). Una vez que estoy seguro de que la imagen existe, le devuelvo la URL.

esperanza que tiene sentido,

Ben

Respuesta

2

Pruebe el siguiente enfoque.

Una clase de modelo para una etiqueta de imagen.

public class ImageModel 
{ 
    public String Source { get; set; } 
    public String Title { get; set; } 
} 

ayudante

public static String Image(this HtmlHelper helper, String source, String title) 
{ 
    var builder = new TagBuilder("img"); 
    builder.MergeAttribute("src", source); 
    builder.MergeAttribute("title", title); 
    return builder.ToString(); 
} 

View con Model.Images de tipo IEnumerable<ImageModel>

...  
<%= Html.Image(Model.Images[0].Source, Model.Images[0].Title) %> 

Acción

public ActionResult ActionName(/*whatever*/) 
{ 
    // ... 
    var model = ...; 
    //... 

    var model0 = ImageModel(); 
    if (Image0.ImageLocation == ImageLocation.AmazonS3) 
     model0.Source = "an amazon url"; 
    else 
     model0.Source = Url.Action("GetImageFromDatabaseOrFileSystem", "MyController", new { Id = Image0.Id }); 
    model0.Title = "some title"; 
    model.Images.Add(model0); 
    // ... 
    return View(model); 
} 

Una acción es una especie de pseudo-código Sin embargo, la idea debe ser clara.

+0

Gracias Anton, este es un buen enfoque. Creo que crearé un nuevo ViewModel para esto ya que mi modelo actual es un IList que tiene IList . Parece mejor romper esto en un nuevo modelo de vista donde puedo definir cosas como el tamaño de imagen requerido y tener solo una imagen por producto (que es todo lo que necesito en mi opinión). Voy a publicar mi código una vez hecho. –

-1

Puede crear una HttpWebRequest para cargar la imagen. Compruebe el encabezado en la respuesta, si es 200 significa que fue exitoso, de lo contrario, algo salió mal.

+0

Hola, el principal requisito es que soy capaz de construir dinámicamente la URL donde basan en el "debe" se encuentra la imagen. No necesito usar HttpWebRequest para verificar que la imagen exista, puedo usar System.IO.File.Exists para esto o consultar el cubo de Amazon S3. Gracias Ben –

1

Después de varias iteraciones he encontrado una solución viable, aunque todavía no estoy convencido de que sea la mejor solución.

Originalmente seguí la sugerencia de Anton y simplemente establecí la url de la imagen en consecuencia dentro de mi acción de controlador. Esto era bastante simple con el siguiente código:

 products.ForEach(p => 
     { 
      p.Images[0].Url = _mediaService.GetImageUrl(p.Images[0], 200); 
     }); 

Sin embargo, pronto me di cuenta de que este enfoque no me dio la flexibilidad que necesitaba. A menudo necesitaré mostrar imágenes de diferentes tamaños y no quiero usar propiedades de mi modelo para esto, como Product.FullSizeImageUrl, Product.ThumbnailImageUrl.

En lo que respecta al "Producto", solo conoce las imágenes que se cargaron originalmente.No necesita saber cómo manipularlos y mostrarlos, o si los almacenamos en caché en Amazon S3.

En formularios web, podría usar un control de usuario para mostrar detalles del producto y luego usar un control de repetidor para mostrar imágenes, estableciendo las URL de la imagen programáticamente en el código.

He encontrado que el uso de RenderAction en ASP.NET MVC me dio una flexibilidad similar:

Acción controlador:

[ChildActionOnly] 
    public ActionResult CatalogImage(CatalogImage image, int targetSize) 
    { 
     image.Url = _mediaService.GetImageUrl(image, targetSize); 
     return PartialView(image); 
    } 

Media Service:

  public MediaCacheLocation CacheLocation { get; set; } 

    public string GetImageUrl(CatalogImage image, int targetSize) 
    { 
     string imageUrl; 

     // check image exists 
     // if not exist, load original image from store (fs or db) 
     // resize and cache to relevant cache location 

     switch (this.CacheLocation) { 
      case MediaCacheLocation.FileSystem: 
       imageUrl = GetFileSystemImageUrl(image, targetSize); 
       break; 
      case MediaCacheLocation.AmazonS3: 
       imageUrl = GetAmazonS3ImageUrl(image, targetSize); 
       break; 
      default: 
       imageUrl = GetDefaultImageUrl(); 
       break; 
     } 

     return imageUrl; 
    } 

HTML helper:

 public static void RenderCatalogImage(this HtmlHelper helper, CatalogImage src, int size) { 
     helper.RenderAction("CatalogImage", "Catalog", new { image = src, targetSize = size }); 
    } 

Uso:

<%Html.RenderCatalogImage(Model.Images[0], 200); %> 

Esto ahora me da la flexibilidad que requiero y apoyará tanto el almacenamiento en caché las imágenes redimensionadas en el disco o guardar en Amazon S3.

Podría hacer con algunos métodos de utilidad de URL para asegurar que la URL de imagen generada sea compatible con SSL/carpetas virtuales. Actualmente estoy usando VirtualPathUtility.

Gracias Ben

Cuestiones relacionadas