ASP.NET MVC Динамически генерируемые URL-адреса изображений - PullRequest
5 голосов
/ 01 февраля 2010

У меня есть приложение ASP.NET MVC, в котором я отображаю изображения.

Эти изображения могут находиться в файловой системе или в базе данных. Это нормально, так как я могу использовать Url.Action в своем изображении, вызвать действие на моем контроллере и вернуть изображение из соответствующего местоположения.

Однако я хочу иметь возможность поддерживать изображения, хранящиеся в Amazon S3. В этом случае я не хочу, чтобы действие моего контроллера возвращало изображение, вместо этого он должен сгенерировать URL-адрес изображения для Amazon S3.

Хотя я мог бы просто выполнить эту логику внутри своего взгляда, например

<% if (Model.Images [0] .ImageLocation == ImageLocation.AmazonS3) {%> // визуализируем изображение amazon

Мне нужно убедиться, что изображение существует первым.

По сути, мне нужно передать значение размера моему контроллеру, чтобы я мог проверить, существует ли изображение такого размера (будь то в базе данных, файловой системе или amazon s3). Как только я уверен, что изображение существует, я возвращаю ему URL.

Надеюсь, что это имеет смысл,

Ben

Ответы [ 3 ]

2 голосов
/ 01 февраля 2010

Попробуйте следующий подход.

Класс модели для тега изображения.

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

Помощник

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();
}

Просмотр с Model.Images типа IEnumerable<ImageModel>

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

Действие

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);
}

Действие - это разновидность псевдокода, однако идея должна быть ясной.

1 голос
/ 02 февраля 2010

После нескольких итераций я нашел работоспособное решение, хотя я все еще не уверен, что это лучшее решение.

Первоначально я последовал совету Антона и просто установил URL изображения в рамках действия моего контроллера.Это было достаточно просто с помощью следующего кода:

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

Однако вскоре я обнаружил, что этот подход не дает мне необходимой гибкости.Часто мне нужно отображать изображения разных размеров, и я не хочу использовать для этого свойства моей модели, такие как Product.FullSizeImageUrl, Product.ThumbnailImageUrl.

Что касается «Продукта», то он знает только об изображениях, которые были первоначально загружены.Ему не нужно знать, как мы манипулируем и отображаем их, или кешируем ли мы их в Amazon S3.

В веб-формах я мог бы использовать пользовательский элемент управления для отображения сведений о продукте, а затем использовать элемент управления повторителя.чтобы отображать изображения, устанавливая URL изображений программно в коде позади.

Я обнаружил, что использование RenderAction в ASP.NET MVC дало мне аналогичную гибкость:

Действие контроллера:

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

Служба мультимедиа:

         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:

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

Использование:

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

Теперь это дает мне необходимую гибкость и будет поддерживатьи кэширование измененных изображений на диск, или сохранение в Amazon S3.

Может быть с некоторыми методами утилит URL, чтобы гарантировать, что сгенерированный URL-адрес изображения поддерживает SSL / виртуальные папки - в настоящее время я использую VirtualPathUtility.

Спасибо, Бен

0 голосов
/ 01 февраля 2010

Вы можете создать HttpWebRequest для загрузки изображения. Проверьте заголовок в ответе, если он равен 200, это означает, что он был успешным, иначе что-то пошло не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...