ASP.NET относительные пути MVC



в моих приложениях мне часто приходится использовать относительные пути. Например, когда я ссылаюсь на JQuery, я обычно делаю так:



<script type="text/javascript" src="../Scripts/jquery-1.2.6.js"></script>


Теперь, когда я делаю переход к MVC, мне нужно учитывать различные пути, которые может иметь страница, относительно корня. Это была, конечно, проблема с переписыванием URL в прошлом, но мне удалось обойти ее, используя последовательные пути.



Я понимаю, что стандартным решением является использование абсолютных путей, таких как:



<script type="text/javascript" src="/Scripts/jquery-1.2.6.js"></script>


но это не будет работать для меня в течение цикла разработки, мне нужно развернуть на тестовой машине, на которой приложение будет работать в виртуальном каталоге. Корневые относительные пути не работают, когда корень изменяется. Кроме того, по причинам обслуживания я не могу просто изменить все пути на время развертывания теста - это было бы кошмаром само по себе.



Так что же самое лучшее решение?



Edit:



Так как этот вопрос все еще получая представления и ответы, я подумал, что было бы разумно обновить его, чтобы отметить, что с Razor V2 поддержка корневых относительных URL-адресов запечена, поэтому вы можете использовать



<img src="~/Content/MyImage.jpg">


без какого-либо синтаксиса на стороне сервера, и механизм просмотра автоматически заменяет ~/ на любой текущий корень сайта.

643   11  

11 ответов:

попробуйте это:

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

или использовать MvcContrib и этого:

<%=Html.ScriptInclude("~/Content/Script/jquery.1.2.6.js")%>

в то время как старый пост, новые читатели должны знать, что Razor 2 и позже (по умолчанию в MVC4+) полностью решает эту проблему.

старый MVC3 с бритвой 1:

<a href="@Url.Content("~/Home")">Application home page</a>

новый MVC4 с бритвой 2 и позже:

<a href="~/Home">Application home page</a>

нет неудобного синтаксиса функции бритвы. Никаких нестандартных тегов разметки.

префикс пути в любых атрибутах HTML с Тильдой ( ' ~ ' ) говорит Razor 2 "просто заставить его работать", подставляя правильный путь. Это здорово.

Breaking change-MVC 5

следите за изменением изменения в MVC 5 (от MVC 5 примечания к выпуску)

Url переписать и Тильда (~)

после обновления до ASP.NET бритва 3 или ASP.NET MVC 5, Тильда (~) нотация может больше не работать правильно, если вы используете перезапись URL. Переписывание URL влияет на обозначение Тильды (~) в HTML-элементах, таких как <A/>,<SCRIPT/>,<LINK/>, и в результате Тильда больше не отображает корневой каталог.

например, если вы переписываете запросы на asp.net/content до asp.net, атрибут href в <A href="~/content/"/> решает / content / content/ вместо /. Чтобы подавить это изменение, можно установить элемент IIS_WasUrlRewritten контекст для false на каждой веб-странице или в Application_BeginRequest in Глобальный.асакс.

они на самом деле не объяснить, как это сделать, но потом я нашел ответ:

если вы работаете в режиме интегрированного конвейера IIS 7 попробуйте поставить следуя в вашем Global.asax:

 protected void Application_BeginRequest(object sender, EventArgs e)
 {
     Request.ServerVariables.Remove("IIS_WasUrlRewritten");
 }

Примечание: Вы можете проверить Request.ServerVariables на самом деле содержит IIS_WasUrlRewritten во-первых, чтобы убедиться, что это то, что ваша проблема.


PS. Я думал, что у меня была ситуация, когда это происходило ко мне, и я получаю src="~/content/..." URL-адреса, созданные в моем HTML-но оказалось, что что-то просто не обновлялось, когда мой код компилировался. Редактирование и повторное сохранение макета и страниц файлов cshtml каким-то образом вызвало что-то работать.

In ASP.NET я обычно использую <img src='<%= VirtualPathUtility.ToAbsolute("~/images/logo.gif") %>' alt="Our Company Logo"/>. Я не понимаю, почему подобное решение не должно работать ASP.NET MVC.

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

то, что я использовал. Измените путь, чтобы соответствовать вашему примеру.

для чего это стоит, я действительно ненавижу идею засорения моего приложения тегами сервера только для разрешения путей, поэтому я сделал немного больше исследований и решил использовать то, что я пробовал раньше для перезаписи ссылок - фильтр ответов. Таким образом, я могу префикс всех абсолютных путей с известным префиксом и заменить его во время выполнения с помощью ответа.Фильтруйте объект и не беспокойтесь о ненужных тегах сервера. Код размещен ниже в случае, если это поможет кому-либо еще.

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

Razor view engine для MVC 3 делает его еще проще и чище использовать виртуальные корневые относительные пути, которые правильно разрешены во время выполнения. Просто перетащите URL-адрес.Метод Content () в значение атрибута href, и он будет правильно разрешен.

<a href="@Url.Content("~/Home")">Application home page</a>

поздно к игре, но этот пост имеет очень Полное резюме обработки ASP.Net тропинки.

Я использую простой вспомогательный метод. Вы можете легко использовать его в представлениях и контроллерах.

разметка:

<a [email protected]()/about">About Us</a>

вспомогательный метод:

public static string Root()
{
    if (HttpContext.Current.Request.Url.Host == "localhost")
    {
        return "";
    }
    else
    {
        return "/productionroot";
    }
}

Я пошел с немного другим подходом, основанным на аналогичном сообщении SO, но с гораздо меньшим количеством кода...

http://a.shinynew.me/post/6042784654/relative-paths-in-asp-net-mvc-javascript

Как и Крис, я действительно не могу терпеть необходимость помещать раздутые теги на стороне сервера внутри моей чистой разметки только для того, чтобы сказать глупую вещь, чтобы смотреть от корня вверх. Это должно быть очень простой, разумной вещью, чтобы попросить. Но мне также ненавистна идея о том, чтобы попытаться написать какие-либо пользовательские классы C#, чтобы сделать такую простую вещь, почему я должен это делать? Какая пустая трата времени.

для меня я просто скомпрометировал "совершенство" и жестко закодировал корень виртуального каталога имя пути внутри ссылок на мой путь. Вот так:

<script type="text/javascript" src="/MyProject/Scripts/jquery-1.2.6.js"></script>

для разрешения URL-адреса не требуется обработка на стороне сервера или код C#, что лучше всего подходит для производительности, хотя я знаю, что это будет незначительно независимо. И никакого раздутого уродливого хаоса на стороне сервера в моей хорошей чистой разметке.

Мне просто придется жить, зная, что это жестко закодировано и должно быть удалено, когда вещь мигрирует в правильный домен вместо http://MyDevServer/MyProject/

Ура

Comments

    Ничего не найдено.