Ответ 1
Попробуйте следующее:
<script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery-1.2.6.js")%>"></script>
Или используйте MvcContrib и выполните следующее:
<%=Html.ScriptInclude("~/Content/Script/jquery.1.2.6.js")%>
В моих приложениях мне часто приходится использовать относительные пути. Например, когда я ссылаюсь на 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">
без синтаксиса на стороне сервера, а механизм просмотра автоматически заменяет ~/любым текущим корнем сайта.
Попробуйте следующее:
<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 с Razor 1:
<a href="@Url.Content("~/Home")">Application home page</a>
Новый MVC4 с Razor 2 и более поздними версиями:
<a href="~/Home">Application home page</a>
Отсутствует неудобный синтаксис функции Razor. Нет нестандартных меток разметки.
Префикс пути в любых атрибутах HTML с тильдой ('~') говорит Razor 2 "просто заставить его работать", заменив правильный путь. Это здорово.
Следите за изменением изменений в MVC 5 (из заметки о выпуске MVC 5)
Переписать Url и Tilde (~)
После перехода на ASP.NET Razor 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 в Global.asax.
На самом деле они не объясняют, как это сделать, но затем я нашел этот ответ:
Если вы работаете в режиме IIS 7 Integrated Pipeline, попробуйте поместить следуя вашему
Global.asax
:
protected void Application_BeginRequest(object sender, EventArgs e)
{
Request.ServerVariables.Remove("IIS_WasUrlRewritten");
}
Примечание. Возможно, вы захотите проверить Request.ServerVariables
на самом деле содержит IIS_WasUrlRewritten
, чтобы убедиться, что это ваша проблема.
PS. Я думал, что у меня была ситуация, когда это происходило со мной, и я получал src="~/content/..."
URLS, сгенерированный в мой HTML-код, но оказалось, что что-то просто не обновлялось при компиляции моего кода. Редактирование и сохранение макетов и файлов cshtml страницы каким-то образом вызвали что-то для работы.
В 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>
Это то, что я использовал. Измените путь в соответствии с вашим примером.
Для чего это стоит, я действительно ненавижу идею забивать мое приложение тегами сервера только для того, чтобы разрешать пути, поэтому я сделал немного больше исследований и решил использовать то, что я пробовал раньше, для переписывания ссылок - фильтра ответов. Таким образом, я могу префикс всех абсолютных путей с известным префиксом и заменить его во время выполнения с помощью объекта 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);
}
}
}
Механизм просмотра Razor для MVC 3 упрощает и упрощает использование относительных путей виртуального корня, которые должным образом разрешены во время выполнения. Просто отбросьте метод Url.Content() в значение атрибута href и он будет правильно исправляться.
<a href="@Url.Content("~/Home")">Application home page</a>
Я пошел с другим подходом, основанным на аналогичной SO-почте, но с гораздо меньшим количеством кода...
http://a.shinynew.me/post/6042784654/relative-paths-in-asp-net-mvc-javascript
Поздно к игре, но этот пост содержит очень полное резюме обработки путей ASP.Net.
Я использую простой вспомогательный метод. Вы можете легко использовать его в представлениях и контроллерах.
Разметка:
<a [email protected]()/about">About Us</a>
Вспомогательный метод:
public static string Root()
{
if (HttpContext.Current.Request.Url.Host == "localhost")
{
return "";
}
else
{
return "/productionroot";
}
}
Как и Крис, я действительно не могу терпеть, чтобы поместить разбухшие теги на стороне сервера в мою чистую разметку просто для того, чтобы рассказать глупой вещи, чтобы смотреть от корня вверх. Это должно быть очень простой и разумной задачей. Но я также ненавижу идею приложить усилия, чтобы написать какие-либо пользовательские классы С#, чтобы сделать такую простую вещь, зачем мне это нужно? Какая пустая трата времени.
Для меня я просто скомпрометировал "совершенство" и жестко закодировал имя корневого каталога виртуального каталога внутри ссылок на пути. Так вот так:
<script type="text/javascript" src="/MyProject/Scripts/jquery-1.2.6.js"></script>
Нет обработки на стороне сервера или кода С#, необходимого для разрешения URL-адреса, что лучше всего подходит для производительности, хотя я знаю, что это будет незначительно. И без раздутого уродливого хаоса на стороне сервера в моей красивой чистой разметке.
Мне просто нужно жить, зная, что это жестко запрограммировано и нужно будет удалить, когда предмет переносится в соответствующий домен вместо http://MyDevServer/MyProject/
Приветствия