在ASP.NET MVC中从相同的路由URL路径提供图像

时间:2009-08-08 03:57:43

标签: asp.net-mvc routing

这就是我想做的事情。我有一些内容,我写的是一个观点。此内容具有与文档相关的图像引用。例如,如果我正在查看以下网址:

http://localhost/article/8AB98/

内容可能包含以下形式的图像:

<img src="myimage.png" />

这显然会导致浏览器在以下网址查询图片:

http://localhost/article/8AB98/myimage.png

但是,由于mvc路由,将无法找到此图像。您知道一种简单的方法可以让该URL将正确的图像返回给浏览器吗?

请注意:实际上重要的是标记保持原始状态不变...这意味着以某种方式重写图像网址,以便它们指向当前视图的URL之外的另一个文件夹是不幸的不可能的。

谢谢!

4 个答案:

答案 0 :(得分:6)

您可以使用Url.Content()方法。

<img src="<%= Url.Content("~/images/myimage.png") %>" />

这将解析应用程序根目录中的URL。

答案 1 :(得分:5)

我假设当你说“实际上重要的是标记与原始标记保持不变”时,你的意思是

<img src="myimage.png" />

是必须呈现给浏览器的内容,因此您需要欺骗Web服务器以获取

的请求URL
http://localhost/article/8AB98/myimage.png

并仅使用该信息查找正确的图像,无论您将图像存储在何处,都将其返回给浏览器。

我想到了两个选项,但很难知道要推荐哪个选项,因为你还没有说明存储图像的位置。

选项1 - 网址重写器

购买ISAPI_Rewrite副本,并重写所有符合上述条件的网址,以便他们随时随地获取图片。有关ISAPI_Rewrite here的更多信息。

选项2 - 自定义HttpHandler

您可以编写映射到所有PNG文件请求的HttpHandler来解析请求URL,并执行查找映像所需的操作,然后将其返回到响应流。这样做的缺点是你必须告诉IIS将所有PNG请求映射到aspnet_isapi.dll,这可能是一个性能无赖。

我仍然不确定我是否正确理解你的问题,但我希望这会有所帮助。祝你好运。

答案 2 :(得分:1)

一种方法是为图像文件添加IgnoreRoute:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("article/{ArticleID}/{name}.png");
    ...

答案 3 :(得分:-1)

我最终使用了@ thinkzig的解决方案,尽管方式略有不同。使用MVC Futures程序集中的FileContent,我只添加了另一条处理图像的路径。

routes.MapRoute("Image", "article/{id}/{image}", new { controller = "Article", action = "Image" });
routes.MapRoute("Article", "article/{id}", new { controller = "Article", action = "Index" });

这个新的操作方法只是根据articleID和图像名称构建文件路径:

public ActionResult Image(string id, string image)
{
    string articlePath = Server.MapPath("~/views/article/");
    string filePath = Path.Combine(articlePath, string.Format("{0}/{1}", id, image));
    return this.File(filePath, "image");
}

还有一件我不得不面对的小事。如果用户访问文章没有一个尾部斜杠(http://localhost/article/8AB98),则浏览器认为articleID是该文件,并尝试查找图像错误文件夹(http://localhost/article/img.png )。

值得庆幸的是,在这种情况下,mvc将请求路由到Article操作,并将图像名称作为“id”参数,因此我只需查找“。”在id中然后使用常规的Image动作来处理它。

文章行动中的

if (id.Contains("."))
{
    return RedirectToImage(id);
}

然后是redirecttoimage代码,它会找出ID和文件名

private ActionResult RedirectToImage(string id)
{
    if (Request.UrlReferrer == null)
    {
        return Content("invalid request");
    }

    var referrer = Request.UrlReferrer.ToString();
    if (referrer.Contains("?"))
    {
        referrer = referrer.Split('?')[0];
    }

    var realId = Path.GetFileName(referrer);
    return this.Image(realId, id);
}

您会注意到我依靠网址引荐来获取实际的文章ID。如果用户试图右键单击图像(在没有斜杠的情况下查看)并选择“在新标签中打开图像”,那么我无法知道文章ID是什么,所以我只返回“无效请求”字符串给用户。这很好,因为在这种情况下我并不是真的想要支持那些用户: - )