我一直在尝试找到一种方法,以编程方式将外部CSS文件的链接添加到Castle MonoRails和NVelocity视图引擎中<head>
标记内的标记的<body>
标记中。任何人都知道如何做到这一点?
我需要解决这个问题,因为我处理的页面可以包含许多“小部件”,每个小部件都可以最佳地获取JS和CSS等其他资产,而不是将<link ..>
放在body标签中和风险渲染问题。
答案 0 :(得分:1)
您是在谈论从视图中将其添加到布局中吗?因为视图是在布局之前呈现的,这意味着如果您创建一个Helper来处理样式块的渲染,那么这将解决您的问题。
意思是,在你的视图或viewcomponent中,你可以调用这样的东西:
$Style.Add("/static/style1.css")
并在你的布局(头部):
$Style.Render()
这是一个示例帮助器(继承AbstractHelper是可选的):
public class StyleHelper : AbstractHelper
{
private readonly HashedSet<string> sheets = new HashedSet<string>();
public void Add( string styleSheet )
{
Add( styleSheet, "all" );
}
public void Add( string styleSheet, string media )
{
this.sheets.Add( String.Format( "media=\"{0}\" href=\"{1}\"", media, styleSheet ) );
}
public string Render()
{
var str = new StringBuilder();
this.sheets.ToList().ForEach( sheet => str.AppendLine( String.Format( "<link rel=\"stylesheet\" {0} />", sheet ) ) );
return str.ToString();
}
}
AbstractHelper是Castle.Monorail.Framework.Helpers的一部分。除非您想要利用该抽象实现公开的功能,否则您不需要继承它。然后,将它添加到您的控制器,您的基本控制器或特定控制器:
[Helper( typeof( StyleHelper ), "Style" )]
public class YourController
答案 1 :(得分:1)
此处发布的解决方案无法正常运行。更好的方法是将脚本添加到httpContext.Current.Items
使用与@jishi相同的结构:
在您的视图或viewcomponent中,您可以调用以下内容:
$Style.Add("/static/style1.css")
并在你的布局(头部):
$Style.Render()
您的帮助程序包含两个使用httpcontext存储和检索文件列表的简单方法。
public class StyleHelper
{
public static void Add(string file) {
if (string.IsNullOrWhiteSpace(file))
return;
var obj = HttpContext.Current.Items["AssetFiles"] as List<string>; // get the collection which might be empty
if (obj == null || obj.Count == 0) {
IList<string> list = new List<string>();
list.Add(file.ToLower());
HttpContext.Current.Items.Add("AssetFiles", list); // adds your first asset to your collection and returns
return;
}
if (obj.Contains(file.ToLower()))
return; // asset is already added
// new asset ready to be added to your collection
obj.Add(file.ToLower());
HttpContext.Current.Items.Add("AssetFiles", obj);
}
public string Render() {
var obj = HttpContext.Current.Items["AssetFiles"] as List<string>;
if (obj == null || obj.Count == 0)
return ""; // you never added anything to the collection. Nothing more to do.
// not using linq here for the sake of readability:
string res = string.Empty;
foreach (var item in obj) {
res = res + string.Format("<link rel=\"stylesheet\" {0} />", item);
}
return res;
}
}
在您的控制器(最好是基本控制器)中添加:
[助手(typeof(StyleHelper),“Style”)] 公共类YourController
答案 2 :(得分:0)
我发现有一个组件完全符合我的要求。
在视图中:
#capturefor(capturefortest)
Default way of printing. Use this for unique variables, such as title.
#end
#blockcomponent(CaptureFor with "id=capturefortest" "append=before")
This will append before 1.
#end
#blockcomponent(CaptureFor with "id=capturefortest" "append")
This will append after 1.
#end
#blockcomponent(CaptureFor with "id=capturefortest" "append")
This will append after 1 and 3.
#end
#blockcomponent(CaptureFor with "id=capturefortest")
Overrides everything defined before this.
#end
$capturefortest
放#时,例如在一个jQuery ID选择器中,在#blockcomponent(CaptureFor)中,你会收到一个错误。这可以通过在AssetFilter中设置一些全局可用变量并使用$ {HASH}来打印#来避免。单引号和引号也很好:
controllerContext.PropertyBag.Add("HASH", "#");
controllerContext.PropertyBag.Add("Q", '"');
controllerContext.PropertyBag.Add("sq", "'");
现在你可以安全地做到:
#blockcomponent(CaptureFor with "id=capturefortest" "append=before")
<script type="text/javascript">
jQuery('#container').html('Awesomeness!')
</script>
#end
答案 3 :(得分:-1)
这可能要归功于Javascript!以下是我将样式添加到<head>
的方法:
<script type="text/javascript">
var cssNode = document.createElement('link');
cssNode.setAttribute('rel', 'stylesheet');
cssNode.setAttribute('href', 'http://path.to/your/file.css');
cssNode.setAttribute('type', 'text/css');
document.getElementsByTagName('head')[0].appendChild(cssNode);
</script>