ASP.NET MVC相对路径

Chr*_*ris 97 asp.net asp.net-mvc

在我的应用程序中,我经常需要使用相对路径.例如,当我引用JQuery时,我通常这样做:

<script type="text/javascript" src="../Scripts/jquery-1.2.6.js"></script>
Run Code Online (Sandbox Code Playgroud)

现在我正在转换到MVC,我需要考虑页面可能具有的相对于根的不同路径.这当然是过去URL重写的问题,但我设法通过使用一致的路径来解决它.

我知道标准解决方案是使用绝对路径,例如:

<script type="text/javascript" src="/Scripts/jquery-1.2.6.js"></script>
Run Code Online (Sandbox Code Playgroud)

但这对我来说不起作用,因为在开发周期中,我必须部署到应用程序将在虚拟目录中运行的测试机器上.根更改时,根相对路径不起作用.此外,出于维护原因,我不能简单地在部署测试期间更改所有路径 - 这本身就是一场噩梦.

那么什么是最好的解决方案?

编辑:

由于这个问题仍在接收观点和答案,我认为更新它可能是谨慎的,因为从Razor V2开始,支持根相对网址,所以你可以使用

<img src="~/Content/MyImage.jpg">
Run Code Online (Sandbox Code Playgroud)

没有任何服务器端语法,视图引擎自动替换〜/当前站点根目录.

Tim*_*ott 92

试试这个:

<script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery-1.2.6.js")%>"></script>
Run Code Online (Sandbox Code Playgroud)

或者使用MvcContrib并执行以下操作:

<%=Html.ScriptInclude("~/Content/Script/jquery.1.2.6.js")%>
Run Code Online (Sandbox Code Playgroud)

  • (我知道这篇文章很旧)-不使用&lt;%= Url.Content(“〜/ Scripts / jquery-1.2.6.js”)%&gt;使服务器呈现路径,但是,如果您使用“ / Scripts / jquery-1.2.6.js”,它将直接提供给客户端,因此,减少了服务器要做的一件事?我以为我读的内容越多,可以避免使用服务器进程越好-尤其是对于* .js路径等静态内容?我意识到这使用了最少的资源,但是如果您的应用程序中有成百上千的Url.Content(),那将节省几纳秒,不是吗? (2认同)

Cha*_*rns 51

虽然是一篇旧帖,新读者应该知道Razor 2及更高版本(MVC4 +中的默认值)完全解决了这个问题.

使用Razor 1的旧MVC3:

<a href="@Url.Content("~/Home")">Application home page</a>
Run Code Online (Sandbox Code Playgroud)

使用Razor 2和更高版本的新MVC4:

<a href="~/Home">Application home page</a>
Run Code Online (Sandbox Code Playgroud)

没有笨拙的Razor函数式语法.没有非标准的标记标记.

使用波形符('〜')在任何HTML属性中添加路径,通过替换正确的路径告诉Razor 2"只使其工作".这很棒.

  • 我经常发现设计越简单,就越有想法. (4认同)

Sim*_*ver 10

突破性的变化 - MVC 5

注意MVC 5中的重大变化(来自MVC 5发行说明)

Url Rewrite和Tilde(〜)

升级到ASP.NET Razor 3或ASP.NET MVC 5后,如果使用URL重写,则波形符(〜)表示法可能无法正常工作.的URL重写影响HTML元素,如波浪线(〜)表示法 <A/>,<SCRIPT/>,<LINK/>,并且作为结果的波形符不再映射到根目录.

例如,如果你重写的请求asp.net/contentasp.net,href属性 <A href="~/content/"/>解析为 /内容/内容/代替/.要禁止此更改,可以在每个Web页面或Global.asax 中的Application_BeginRequest中将IIS_WasUrlRewritten上下文设置为false .

他们实际上没有解释如何做到这一点,但后来我找到了这个答案:

如果您在IIS 7集成管道模式下运行,请尝试将以下内容放入Global.asax:

 protected void Application_BeginRequest(object sender, EventArgs e)
 {
     Request.ServerVariables.Remove("IIS_WasUrlRewritten");
 }
Run Code Online (Sandbox Code Playgroud)

注意:您可能需要首先检查Request.ServerVariables实际包含IIS_WasUrlRewritten,以确保这是您的问题所在.


PS.我以为我遇到过这样的情况,我正在将src="~/content/..."URL生成到我的HTML中 - 但事实证明,当我的代码编译时,某些内容并不令人耳目一新.编辑和重新保存布局和页面cshtml文件以某种方式触发了一些工作.


Dav*_*emp 6

在ASP.NET中我经常使用<img src='<%= VirtualPathUtility.ToAbsolute("~/images/logo.gif") %>' alt="Our Company Logo"/>.我不明白为什么类似的解决方案不适用于ASP.NET MVC.


Jes*_*alm 6

<script src="<%=ResolveUrl("~/Scripts/jquery-1.2.6.min.js") %>" type="text/javascript"></script>
Run Code Online (Sandbox Code Playgroud)

是我用过的.更改路径以匹配您的示例.


Chr*_*ris 5

对于它的价值,我真的很讨厌用服务器标签乱扔我的应用只是为了解决路径,所以我做了一些研究,并选择使用我之前尝试过的重写链接 - 响应过滤器.通过这种方式,我可以使用已知前缀为所有绝对路径添加前缀,并在运行时使用Response.Filter对象替换它,而不必担心不必要的服务器标记.代码发布在下面,以防它可以帮助其他任何人.

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Demo
{
    public class PathRewriter : Stream
    {
        Stream filter;
        HttpContext context;
        object writeLock = new object();
        StringBuilder sb = new StringBuilder();

        Regex eofTag = new Regex("</html>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        Regex rootTag = new Regex("/_AppRoot_", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        public PathRewriter(Stream filter, HttpContext context)
        {
            this.filter = filter;
            this.context = context;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            string temp;

            lock (writeLock)
            {
                temp = Encoding.UTF8.GetString(buffer, offset, count);
                sb.Append(temp);

                if (eofTag.IsMatch(temp))
                    RewritePaths();
            }
        }

        public void RewritePaths()
        {
            byte[] buffer;
            string temp;
            string root;

            temp = sb.ToString();
            root = context.Request.ApplicationPath;
            if (root == "/") root = "";

            temp = rootTag.Replace(temp, root);
            buffer = Encoding.UTF8.GetBytes(temp);
            filter.Write(buffer, 0, buffer.Length);
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return filter.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            return;
        }

        public override long Length
        {
            get { return Encoding.UTF8.GetBytes(sb.ToString()).Length; }
        }

        public override long Position
        {
            get { return filter.Position; }
            set { filter.Position = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return filter.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return filter.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }
    }

    public class PathFilterModule : IHttpModule
    {
        public void Dispose()
        {
            return;
        }

        public void Init(HttpApplication context)
        {
            context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
        }

        void context_ReleaseRequestState(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            if (app.Response.ContentType == "text/html")
                app.Response.Filter = new PathRewriter(app.Response.Filter, app.Context);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)