Asp.net mvc 3 在Razor视图上处理嵌入式资源的正确方法是什么?

Asp.net mvc 3 在Razor视图上处理嵌入式资源的正确方法是什么?,asp.net-mvc-3,razor,embedded-resource,Asp.net Mvc 3,Razor,Embedded Resource,我正在将一些代码从ASPX视图引擎迁移到Razor,我遇到了一个障碍 我有以下代码: <link rel="Stylesheet" type="text/css" href=" <%=Page.ClientScript.GetWebResourceUrl (typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty

我正在将一些代码从ASPX视图引擎迁移到Razor,我遇到了一个障碍

我有以下代码:

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

这里的问题是,使用Razor,我没有页面属性

所以我退了一步,我想知道:在Razor中获得嵌入式资源的正确方法是什么

我花了很多时间试图找到这个问题的解决方案,但除了“在助手中包装一个新页面”之外,我还没有找到任何其他解决方案


这是唯一的办法吗?或者还有更正确的吗?

不幸的是,web资源与webforms基础架构紧密相连,没有它很难重用它们。所以有点粗糙,但你可以写一个助手:

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处理程序/控制器,该处理程序/控制器将从程序集中读取嵌入式资源,并通过设置适当的内容类型将其流式传输到响应。

除了调用
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视图中使用WebResourceURL不是很有用。相反,建议直接将资源放入MVC应用程序的“内容”或“脚本”文件夹中

但是,如果您想在无法将内容放入目标项目的共享类库中编写
HtmlHelper
函数,情况就会发生变化


根本原因 这种方法基本上避免了在每次调用
GetWebResourceUrl
时创建一个新的、庞大的
Page
对象

查看上下文,结果发现
页面
脚本管理器
上下文是徒劳的。因此,直接调用
AssemblyResourceLoader.GetWebResourceUrlInternal
将一针见血创建工作的WebResource.axd URL所需的就是程序集,当然还有资源名

缺点是该函数是内部函数,因此必须由反射调用。然而,上述实现避免了每次通过反射调用函数的开销。相反,
CreateDelegate
只用于获取一个普通委托,该委托几乎可以在没有开销的情况下调用


访问字段
GetWebResourceUrlInternal
时的竞争条件是预期的。它不会造成任何重大伤害,因为它不太可能在第一次调用时遇到这个包含多个并行线程的代码片段,即使发生这种情况,结果仍然是可靠的。

在这种情况下,哪一个更好?@Adeel,我从不使用嵌入式CSS或javascript,所以我没有足够的经验来判断哪一个更好。我认为重用WebForms的webresources可以解决缓存等问题。。。所以可能更好。
typeof(SomeClassInTheSameAssembly).Assembly.GetWebResourceUrl("Namespace.Resource.xxx")