2010-02-01 90 views
5

我有一个ASP.NET MVC应用程序,我正在显示图像。ASP.NET MVC动态生成的图像URL

这些图像可能位于文件系统或数据库内。这很好,因为我可以在图像中使用Url.Action,在我的控制器上调用该操作并从相关位置返回图像。

但是,我希望能够支持存储在Amazon S3中的图像。在这种情况下,我不希望我的控制器操作返回图像,而应该为Amazon S3生成图像URL。

虽然我可以在我的视图内执行这个逻辑,例如

<%如果(Model.Images [0] == .ImageLocation ImageLocation.AmazonS3){%> //渲染亚马逊图像

我需要确保图像第一存在。

本质上,我需要传递一个大小值到我的控制器,以便我可以检查图像是否以该大小存在(无论是在数据库,文件系统还是亚马逊S3中)。一旦我确信图像存在,然后我将URL返回给它。

希望是有道理的,

回答

2

请尝试以下方法。

图像标签的模型类。

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

的行动是一种伪代码但是这个想法应该清楚。

+0

谢谢安东,这是很好的方法。我想我会为此创建一个新的ViewModel,因为我目前的模型是IList ,它具有IList 。 似乎更好地将其分解为新的视图模型,在该模型中,我可以定义所需图像大小等事物,并且每个产品只有一个图像(这正是我所需要的)。 我会在完成后发布我的代码。 – 2010-02-01 18:40:26

-1

您可以创建一个HttpWebRequest加载图像。检查响应中的标题,如果它是200表示成功,否则出现问题。

+0

嗨,主要的要求是,我能够构造URL动态基础上,在图像“应当”来定位。我不需要使用HttpWebRequest来检查映像是否存在,我可以使用System.IO.File.Exists进行此操作或检查Amazon S3存储桶。 谢谢 本 – 2010-02-01 15:48:50

1

经过几次迭代后,我想出了一个可行的解决方案,但我仍然不相信它是最好的解决方案。

本来我遵循安东的建议,只是在我的控制器操作中设置图像URL。这很简单,下面的代码:

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

但是,我很快发现这种方法没有给我我需要的灵活性。通常我需要显示不同大小的图像,而且我不想使用我的模型的属性,例如Product.FullSizeImageUrl,Product.ThumbnailImageUrl。

就“产品”而言,它只知道最初上传的图像。它不需要知道我们如何操作和显示它们,或者我们是否将它们缓存在Amazon S3中。

在网络表单中,我可能会使用用户控件来显示产品详细信息,然后使用中继器控件来显示图像,在代码后面以编程方式设置图像url。

我发现,在ASP.NET MVC中使用的的RenderAction给了我类似的灵活性:

控制器动作:

[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。

感谢 本