Asp.net mvc 在ASP.NET MVC中为来自相同路由URL路径的图像提供服务

Asp.net mvc 在ASP.NET MVC中为来自相同路由URL路径的图像提供服务,asp.net-mvc,routing,Asp.net Mvc,Routing,这是我想做的。我有我正在写的内容给一个视图。此内容具有与文档相关的图像引用。例如,如果我正在查看以下URL: http://localhost/article/8AB98/ http://localhost/article/8AB98/myimage.png 内容可能具有以下形式的图像: <img src="myimage.png" /> 但是,由于mvc路由,无法找到此映像。你知道一个简单的方法,我可以使该URL返回正确的图像到浏览器 请注意:标记与原始标记保持一致,这一点非

这是我想做的。我有我正在写的内容给一个视图。此内容具有与文档相关的图像引用。例如,如果我正在查看以下URL:

http://localhost/article/8AB98/
http://localhost/article/8AB98/myimage.png
内容可能具有以下形式的图像:

<img src="myimage.png" />
但是,由于mvc路由,无法找到此映像。你知道一个简单的方法,我可以使该URL返回正确的图像到浏览器

请注意:标记与原始标记保持一致,这一点非常重要。。。这意味着,以某种方式重新编写图像URL,以便它们指向当前视图URL之外的另一个文件夹,不幸的是,这是不可能的


谢谢

一种方法是为图像文件设置IgnoreRoute:

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

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

“/>

这将从应用程序根目录解析url。

我假设当您说“标记保持与原始标记相同实际上很重要”时,您的意思是

<img src="myimage.png" />
并仅使用该信息查找正确的图像(无论存储在何处),然后将其返回到浏览器

我想到了两个选项,但很难知道该推荐哪一个,因为您还没有说图像存储在哪里

选项1-Url重写器

购买一份ISAPI_Rewrite的副本,并将符合上述标准的所有URL重写,以便它们可以在图像所在的任何位置获取图像。有关ISAPI_Rewrite的更多信息

选项2-自定义HttpHandler

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


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

我最终使用了@thinkzig的解决方案,尽管方式略有不同。使用MVC Futures assembly中的文件内容,我只是添加了另一种处理图像的方法

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将请求路由到带有图像名称作为“id”参数的Article action,因此我只需在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);
}

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

我也想写一个帮助程序,这样你就可以只使用Html.Image(“~/images/myimage.png”,“myAltText”);你的helper方法基本上会返回Phil的代码。。。将URL从“myimage.png”更改为URL.content将返回的内容是不可能的,因为内容的标记不能更改。除此之外,我实际上需要将这个标记()呈现给浏览器(正如@thinkzig所提到的)我并没有完全使用您的两个选项,但这最终是解决问题的解决方案:-)我将发布另一个问题的答案和细节
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");
}
if (id.Contains("."))
{
    return 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);
}