Подтвердить что ты не робот

Автоматическое разрешение URL-адреса ASP.NET MVC в файлах CSS

В обычном сценарии WebForms любые корневые URL-адреса (например, ~/folder/file.txt) внутри CSS файлов, таких как:

.form { background-image: url(~/Content/Images/form_bg.gif); }

автоматически будет разрешен во время выполнения, если я укажу

<head runat="server">

На странице ссылок.

Однако это больше не происходит на веб-сайте ASP.NET MVC Beta1.

Можно ли включить эту функцию, не прибегая к хакам или файлу загрузчика CSS? Например, HttpModules или что-то еще?

Или я не правильно задаю свой сайт? Что должно быть хорошим дизайном?

Поскольку у исходных ASP.NET WebForms уже есть эта функция, я бы предпочел использовать любую существующую функциональность, если это возможно. Но я не очень понимаю.

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


EDIT: Я имею в виду URL-адрес в файле CONTENT, а не сам URL-адрес файла.

4b9b3361

Ответ 1

Я бы не стал беспокоиться об автокорневом значении ~. Я понимаю, что вы хотите, чтобы одно и то же решение работало там, где корневой каталог отличается от развертывания, но в документе CSS у вас не должно быть проблем с использованием относительных путей. Пути в документе CSS (к URL-адресу изображения в вашем примере) всегда будут относиться к расположению файла CSS независимо от пути к любой странице, загружающей этот файл CSS. Поэтому, если ваши изображения находятся в ~/Content/Images, а ваши таблицы стилей находятся в ~/Content/Stylesheets, вы всегда сможете использовать background-image: url(../Images/form_bg.gif);, и он будет работать независимо от местоположения страницы, загружающей таблицу стилей.

Есть ли причина, по которой это не сработает?

Ответ 2

Один трюк, который я использовал в прошлом, состоял в том, чтобы на самом деле сделать мой CSS файл имеющим расширение .ASPX и установить свойство ContentType в сигнатуре страницы:

<%@ Page Language="C#" ContentType="text/css" %>

body {
    margin: 0;
    padding: 0;
    background: #C32605 url(<%= ResolveUrl("~/Content/themes/base/images/BodyBackground.png") %>) repeat-x;
    font-family: Verdana, Arial, sans-serif;
    font-size: small;
    color: #d7f9ff;
}

Это гарантирует, что файл CSS проходит через структуру ASP.NET и заменяет код на стороне сервера вашим относительным путем.

Ответ 3

Здесь some ресурсы по внедрению IHttpModule для перехвата веб-запросов в вашем приложении...

Записать/настроить один для проверки типа файла (например, псевдокода: if (запрос заканчивается на ".css" )...)

затем используйте регулярное выражение, чтобы заменить все экземпляры "~/" на System.Web.VirtualPathUtility.ToAbsolute( "~/" )

Я не знаю, что это будет делать с производительностью, выполняя каждый запрос с помощью такого типа фильтра, но вы, вероятно, можете поиграть с вашим файлом web.config и/или вашими URL-адресами URL-адреса MVC для перебора всех запросов .css через этот вид фильтра, пропуская его для других файлов.

Подумайте об этом, вы, вероятно, можете добиться такого же эффекта в приложении ASP.NET MVC, указав все свои рефлексии CSS на специальный контроллер, который выполняет такую ​​предварительную обработку для вас. Я сомневаюсь, что это было бы так же хорошо, как и IHttpModule.

Ответ 4

Если вы пытаетесь разобрать ~/ из любого файла, включая текстовые файлы, javascript и т.д., вы можете написать обработчик, который назначает ему фильтр, и вы можете использовать его для поиск этих путей... например...

public class StringParsingFilter : MemoryStream {

    public Stream OriginalStream {
        get { return this.m_OriginalStream; }
        set { this.m_OriginalStream = value; }
    }
    private System.IO.Stream m_OriginalStream;

    public StringParsingFilter() : base() {
        this.m_OriginalStream = null;
    }

    public override void Flush() {
        this.m_OriginalStream.Flush();
    }

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

        //otherwise, parse for the correct content
        string value = System.Text.Encoding.Default.GetString(buffer);
        string contentType = HttpContext.Current.Response.ContentType;

        //Do any parsing here
        ...

        //write the new bytes to the stream
        byte[] bytes = System.Text.Encoding.Default.GetBytes(value);
        this.m_OriginalStream.Write(bytes, offset, count + (bytes.Length - buffer.Length));

    }

}

И вы напишите пользовательский обработчик, чтобы узнать, когда следует назначить этот фильтр... например следующее...

 public class FilterControlModule : IHttpModule {

    public void Init(HttpApplication context) {
        HttpApplication oAppContext = context;
        oAppContext.BeginRequest += new EventHandler(_HandleSettingFilter);                        
    }

    private void _HandleSettingFilter(object sender, EventArgs e) {

        //You might check the file at this part to make sure
        //it is a file type you want to parse
        //if (!CurrentFile.isStyleSheet()) { return; }
        ...

        //assign the new filter
        StringParsingFilter filter = new StringParsingFilter();
        filter.OriginalStream = HttpContext.Current.Response.Filter;
        HttpContext.Current.Response.Filter = (Stream)filter;

    }

}

Возможно, проще было просто сказать "искать IHttpModules", но это код, который я использовал для анализа файлов для путей, отличных от файлов ASP.net.

Вам также придется изменить некоторые параметры в настройках IIS, чтобы разрешить обработку файлов, установив ASP.NET ISAPI в качестве шаблона для всех файлов, которые обрабатываются. Вы можете увидеть больше на этом веб-сайте, если вы используете IIS6, который...

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

Ответ 5

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

Ответ 6

Я создал класс PathHelper util, который дает мне все пути, которые мне нужны. Например

<link href="<%=PathHelper.CssUrl("FormulaIndex.css")%>" rel="Stylesheet" type="text/css"/>

Дает мне правильный полный url с помощью System.Web.VirtualPathUtility.ToAbsolute() и моего собственного соглашения (content/css/yourFile.css).

Я сделал то же самое для js, xml, t9n, pics... Его центральный, многоразовый, и теперь мне нужно было только изменить одну строку, чтобы поймать перемещение папки сценариев из содержимого /js в скрипты на всех моих веб-сайтах и ​​страницах.

Моральный ход, если вы спросите меня, но это реальность в текущей бета-версии: (