Как правильно обращаться со встроенными ресурсами в Razor View? - PullRequest
6 голосов
/ 14 февраля 2011

Я перенесу некоторый код из механизма просмотра ASPX в Razor и наткнулся на контрольно-пропускной пункт.

У меня есть этот код:

<link rel="Stylesheet" type="text/css" href="
    <%=Page.ClientScript.GetWebResourceUrl
        (typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), 
        "DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector.css")%>" />

Проблема здесьчто с Razor, у меня нет свойства Page.

Так что я на секунду отступил на шаг, и я задаюсь вопросом: как правильно получить встроенные ресурсы в Razor?

Я потратил немало времени, пытаясь найти решения по этому вопросу, но на самом деле я не нашел ничего, кроме как «обернуть новую страницу помощником»

Это единственный способсделать это?Или есть что-то более правильное?

Ответы [ 2 ]

7 голосов
/ 14 февраля 2011

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

public static class UrlExtensions
{
    public static string WebResource(this UrlHelper urlHelper, Type type, string resourcePath)
    {
        var page = new Page();
        return page.ClientScript.GetWebResourceUrl(type, resourcePath);
    }
}

и в своем представлении бритвы:

<link rel="stylesheet" type="text/css" href="@Url.WebResource(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector.css")" />

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

0 голосов
/ 21 ноября 2017

Помимо вызова new Page()... вы можете напрямую вызывать базовую реализацию.Поместите этот код в некоторый статический класс:

public static string GetWebResourceUrl(this Assembly assembly, string name)
{ if (GetWebResourceUrlInternal == null)
  GetWebResourceUrlInternal = (Func<Assembly,string,bool,bool,System.Web.UI.ScriptManager,string>)
    typeof(System.Web.Handlers.AssemblyResourceLoader)
      .GetMethod("GetWebResourceUrlInternal", BindingFlags.NonPublic|BindingFlags.Static, null,
        new[]{typeof(Assembly),typeof(string),typeof(bool),typeof(bool),typeof(System.Web.UI.ScriptManager)}, null)
      .CreateDelegate(typeof(Func<Assembly,string,bool,bool,System.Web.UI.ScriptManager,string>));
  return GetWebResourceUrlInternal(assembly, name, false, false, null);
}
volatile static Func<Assembly,string,bool,bool,System.Web.UI.ScriptManager,string> GetWebResourceUrlInternal = null;

И в представлении Razor или в коде, лежащем за ним:

typeof(SomeClassInTheSameAssembly).Assembly.GetWebResourceUrl("Namespace.Resource.xxx")

Конечно, использование URL-адресов WebResource в представлениях Razor не очень полезно.Вместо этого рекомендуется поместить ресурс в папку Content или Scripts вашего MVC-приложения напрямую.

Но ситуация изменится, если вы захотите записать HtmlHelper функций в разделяемых библиотеках классов , которыене может поместить содержимое в целевой проект.


Обоснование

При таком подходе в основном избегается создание нового громоздкого объекта Page при каждом вызове GetWebResourceUrl.

Глядя на исходный код , получается, что контекст Page и ScriptManager используется просто даром.Так что, вызывая AssemblyResourceLoader.GetWebResourceUrlInternal, вы попадете прямо в ноготь на голове. Все, что вам нужно для создания рабочего URL WebResource.axd - это сборка и, конечно, имя ресурса .

Недостаток:что эта функция внутренняя , поэтому она должна вызываться отражением.Однако вышеприведенная реализация позволяет избежать затрат на вызов функции путем отражения каждый раз.Вместо этого CreateDelegate используется один раз для получения обычного делегата, который может быть вызван почти без дополнительных затрат.

Предусмотрено состояние гонки при доступе к полю GetWebResourceUrlInternal.Это не наносит существенного вреда, поскольку очень маловероятно, что при первом вызове он столкнется с этим фрагментом кода со многими параллельными потоками, и даже если это произойдет, результат все еще надежен.

...