MVC Razor,包括来自另一个项目的JS/CSS文件
本文关键字:JS CSS 文件 项目 另一个 Razor 包括 MVC | 更新日期: 2024-10-24 02:27:10
我有一个使用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>
我就是这么做的。然而,我将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) 将所有要共享的脚本放在Common.Web''scripts中
2) 对于Web应用程序中的每个脚本文件,"添加为链接"到您的Common.Web脚本(您甚至不需要执行此步骤;不过,很高兴看到您的Web应用程序在VS中使用了哪些脚本)
3) 将生成后事件添加到Web应用程序,该事件将脚本从Common.Web''scripts复制到WebApp''scripts文件夹:
复制$(ProjectDir)。。''Common.Web''Scripts*$(ProjectDir)''Scripts
因此,从Visual Studio的角度来看,您将只有一个地方可以更新可供多个项目使用的.js文件。
不使用Url
帮助程序,而是使用相对寻址。您尝试做的事情毫无意义,因为helper用于解析相对于其项目的路径。
由于您正在尝试使用另一个项目的资源,因此可以假设您提前知道将在哪里部署每个项目。尽管我不喜欢这种做法,但我可以想出一个务实的解决方案。
如果您的两个应用程序位于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>
意思是,解析我的应用程序根文件夹,上升一个级别,然后下降到路径的其余部分。
我刚刚在寻找相同答案时发现了这个问题。感谢之前的海报,他们明确表示,仅靠Visual Studio是无法做到这一点的:最终总是得到原始文件的副本或一组不完整的运输文件。
每当我有简单的通用功能时,我不想重新发明轮子,所以我在硬盘上有一个通用脚本文件夹:/通用/Javascript
我的web项目位于:/项目名称
所以我的常用脚本在我的web项目之外。
我通过源代码管理解决了这个问题。大多数源代码管理存储库都具有在另一个目录中显示文件的功能。我的步骤是:
- 在我的VS项目下创建空文件夹:/ProjectName/Scripts/Common
- 将空文件夹提交给源代码管理
- 使用Subversion(我的源代码管理),我设置了一个"extern",以便将我的公共文件链接到新文件夹。其他源代码管理软件可能称之为"链接"或其他类似的东西
- 更新了新文件夹,我的常用Javascript文件就出现了,现在可以添加到我在Visual Studio中的web项目中
显然,我通过在VisualStudio中更改文件并提交文件来测试这一点。这些更改确实反映在位于/Common/Javascript中的原始文件中。
我现在可以简单地向任何其他需要使用相同功能的web项目添加一个extern:当然,现在更改这些文件会带来额外的风险,因为我可能会意外地破坏其他使用它们的项目。虽然我可以将extern配置为使用文件的特定修订版,但这不是我现在想要做的;我将等待这种复杂性的出现。