MVC Razor,包含来自另一个项目的JS / CSS文件

时间:2012-08-07 09:29:29

标签: c# javascript asp.net-mvc razor

我有一个使用Razor语法的C#MVC项目 为了能够重用一些代码,我想将一些JavaScript和CSS文件放在一个不同的项目中并以某种方式包含它们。
这就是我的脚本目前的包含方式:

<script src="@Url.Content("~/Scripts/bootstrap-typeahead.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/bootstrap-dropdown.js")" type="text/javascript"></script>

目前,脚本与cshtml文件位于同一个项目中,但它们应该放在Common.Web项目中而不是...
我想做的是这个(虽然不起作用):

<script src="@Url.Content("Common.Web/Scripts/bootstrap-typeahead.js")" type="text/javascript"></script>
<script src="@Url.Content("Common.Web/Scripts/bootstrap-dropdown.js")" type="text/javascript"></script>

4 个答案:

答案 0 :(得分:12)

我这样做。但是我将Javascript文件和其他内容嵌入到另一个DLL中,然后从我的剃刀语法中调用它们。这是我使用的代码。 在视图中: 脚本示例:

        <script src=@Url.Action("GetEmbeddedResource", "Shared", new { resourceName = "Namespace.Scripts.jquery.qtip.min.js", pluginAssemblyName = @Url.Content("~/bin/Namespace.dll") }) type="text/javascript" ></script>

图片示例:

@Html.EmbeddedImage("corporate.gif", new { width = 150, height = 50})

这是我的助手方法:

        public static MvcHtmlString EmbeddedImage(this HtmlHelper htmlHelper, string imageName, dynamic htmlAttributes)
    {
        UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
        var anchor = new TagBuilder("img");
        anchor.Attributes["src"] = url.Action("GetEmbeddedResource", "Shared",
                                              new
                                                  {
                                                      resourceName = "Namespace.Content.Images." + imageName,
                                                      pluginAssemblyName = url.Content("~/bin/Namespace.dll")
                                                  });

        if (htmlAttributes != null)
        {
            string width = "";
            string height = "";
            PropertyInfo pi = htmlAttributes.GetType().GetProperty("width");
            if (pi != null)
                width = pi.GetValue(htmlAttributes, null).ToString();

            pi = htmlAttributes.GetType().GetProperty("height");
            if (pi != null)
                height = pi.GetValue(htmlAttributes, null).ToString();

            if (!string.IsNullOrEmpty(height))
                anchor.Attributes["height"] = height;

            if (!string.IsNullOrEmpty(width))
                anchor.Attributes["width"] = width;
        }
        return MvcHtmlString.Create(anchor.ToString());
    }

最后我的共享控制器:

        [HttpGet]
    public FileStreamResult GetEmbeddedResource(string pluginAssemblyName, string resourceName)
    {
        try
        {
            string physicalPath = Server.MapPath(pluginAssemblyName);
            Stream stream = ResourceHelper.GetEmbeddedResource(physicalPath, resourceName);
            return new FileStreamResult(stream, GetMediaType(resourceName));
            //return new FileStreamResult(stream, GetMediaType(tempResourceName));
        }
        catch (Exception)
        {
            return new FileStreamResult(new MemoryStream(), GetMediaType(resourceName));
        }
    }

    private string GetMediaType(string fileId)
    {
        if (fileId.EndsWith(".js"))
        {
            return "text/javascript";
        }
        else if (fileId.EndsWith(".css"))
        {
            return "text/css";
        }
        else if (fileId.EndsWith(".jpg"))
        {
            return "image/jpeg";
        }
        else if (fileId.EndsWith(".gif"))
        {
            return "image/gif";
        }
        else if (fileId.EndsWith(".png"))
        {
            return "image/png";
        }
        return "text";
    }

资源助手:

    public static class ResourceHelper
{
    public static Stream GetEmbeddedResource(string physicalPath, string resourceName)
    {
        try
        {
            Assembly assembly = PluginHelper.LoadPluginByPathName<Assembly>(physicalPath);

            if (assembly != null)
            {
                string tempResourceName = assembly.GetManifestResourceNames().ToList().FirstOrDefault(f => f.EndsWith(resourceName));
                if (tempResourceName == null)
                    return null;
                return assembly.GetManifestResourceStream(tempResourceName);
            }
        }
        catch (Exception)
        {

        }

        return null;
    }
}  

插件助手

public static T LoadPluginByPathName<T>(string pathName)
{
    string viewType = typeof(T).GUID.ToString();

    if (HttpRuntime.Cache[viewType] != null)
        return HttpRuntime.Cache[viewType] is T ? (T)HttpRuntime.Cache[viewType] : default(T);

    object plugin = Assembly.LoadFrom(pathName);
    if (plugin != null)
    {
        //Cache this object as we want to only load this assembly into memory once.
        HttpRuntime.Cache.Insert(viewType, plugin);
        return (T)plugin;
    }

    return default(T);
}

请记住,我将这些用作嵌入内容!

答案 1 :(得分:6)

据我所知,你不能这样做,因为路径不在网站之外。

但您可以执行以下操作:

1)将您要共享的所有脚本放在Common.Web \ Scripts中 2)对于Web应用程序'Add as Link'中的每个脚本文件到您的Common.Web脚本(您甚至不需要执行此步骤;但是很高兴看到您的Web应用程序在VS中使用了哪些脚本
3)向Web应用程序添加一个构建后事件,将事件从Common.Web \ Scripts复制到WebApp \ Scripts文件夹:

  

复制$(ProjectDir).. \ Common.Web \ Scripts * $(ProjectDir)\ Scripts

因此,从您在Visual Studio中的角度来看,您将只有一个位置来更新可供多个项目使用的.js文件。

答案 2 :(得分:1)

而不是使用Url帮助程序使用相对寻址。您尝试做的事情毫无意义,因为帮助程序用于解析与其项目相关的路径。

由于您正在尝试使用其他项目的资源,因此可以假设您事先知道要部署每个项目的位置。即使我不喜欢这种做法,我也能想到一个实用的解决方案。


如果您的两个申请是在网址:

http://www.mysite.com/app1
http://www.mysite.com/Common.Web
你可以这样说:

<script src="@Url.Content("~")/../Common.Web/Scripts/bootstrap-typeahead.js")" type="text/javascript"></script>

意思是,解析我的应用根文件夹,上一层,然后沿着路径的其余部分继续。

答案 3 :(得分:-1)

我在寻找相同的答案时发现了这个问题。感谢之前的海报,他们明确表示仅使用Visual Studio无法做到这一点:您将始终最终获得原始文件的副本或一组不完整的送货文件。

每当我有简单的常用功能时,我都不想重新发明轮子,所以我的硬盘上有一个常用脚本的文件夹: /常用/使用Javascript

我的网络项目位于: /项目名

所以我的常用脚本不在我的网络项目之内。

我通过源代码控制解决了这个问题。大多数源代码控制存储库都具有在另一个目录中显示文件的功能。我的步骤是:

  1. 在我的VS项目下创建空文件夹:/ ProjectName / Scripts / Common
  2. 将空文件夹提交给源代码管理
  3. 使用Subversion(我的源代码控制),我设置了一个&#34; extern&#34;这样我的公共文件就链接到了新文件夹。其他源控制软件可以将此称为“#34; link&#34;或者其他一些这样的事情。
  4. 更新了新文件夹,我的常用Javascript文件进来了,现在可以添加到我在Visual Studio中的Web项目中。
  5. 显然,我通过更改Visual Studio中的文件并提交它们来测试它。这些更改确实反映在原始文件中,位于/ Common / Javascript。

    我现在可以简单地将extern添加到需要使用相同功能的任何其他Web项目中:当然,更改这些文件现在会带来额外的风险,因为我可能会意外地破坏使用它们的其他项目。虽然我可以配置extern来使用文件的特定修订版,但这不是我想要做的事情;我将等待它发生时的复杂性。