有没有办法从 MVC 控制器拦截页面生命周期并在页面或 DOM 的某处注入代码?我想将 HTML、CSS 和 JavaScript 添加到页面页眉和页脚,但不将它们添加到嵌入在某个程序集中的 _Layout 视图中。所以我想从 Global.asax / Application_Start 的控制器中执行此操作。这可能吗?
问问题
955 次
1 回答
2
我做了类似的事情。
首先,您需要在布局文件中添加占位符(要在其中注入代码)
其次,您需要在 global.asax 中添加一个全局 ActionFilterAttribute。在 FilterAttribute 中,仅覆盖筛选 OnActionExecuted 并仅筛选 ViewResults。
第三,您需要更改 Response.Filter,使用一个新的过滤器来搜索 html 代码中的占位符,并将其替换为您自己的。
我就是这么写的,我添加了一种在代码中任意位置声明 Styles & Scripts 的方法,当结果完成后,资源被注入到 head 标签中。
public class DynamicHeaderHandler : ActionFilterAttribute
{
private static readonly byte[] _headClosingTagBuffer = Encoding.UTF8.GetBytes("</head>");
private static readonly byte[] _placeholderBuffer = Encoding.UTF8.GetBytes(DynamicHeader.SectionPlaceholder);
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result is ViewResult)
{
filterContext.HttpContext.Response.Filter = new ResponseFilter(filterContext.HttpContext.Response.Filter);
}
base.OnActionExecuted(filterContext);
}
private class ResponseFilter : MemoryStream
{
private readonly Stream _outputStream;
public ResponseFilter(Stream aOutputStream)
{
_outputStream = aOutputStream;
}
public override void Close()
{
_outputStream.Flush();
_outputStream.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
var maxIndex = IndexOfSubArray(buffer, _headClosingTagBuffer);
var index = IndexOfSubArray(buffer, _placeholderBuffer, maxIndex);
if (index == -1)
{
_outputStream.Write(buffer, offset, count);
}
else
{
var html = DynamicHeader.GetHtml();
var injectBytes = Encoding.UTF8.GetBytes(html);
var newBuffer = buffer.Take(index).Concat(injectBytes).Concat(buffer.Skip(index + _placeholderBuffer.Length)).ToArray();
_outputStream.Write(newBuffer, 0, newBuffer.Length);
}
}
private static int IndexOfSubArray(byte[] aBuffer, byte[] aSubBuffer, int aMaxIndex = int.MaxValue)
{
if (aBuffer.Length < aSubBuffer.Length)
{
return -1;
}
for (var outerIndex = 0; outerIndex < aBuffer.Length && outerIndex < aMaxIndex; ++outerIndex)
{
var isEqual = true;
for (int subInnerIndex = 0, innerIndex = outerIndex; subInnerIndex < aSubBuffer.Length && innerIndex < aBuffer.Length; ++subInnerIndex, ++innerIndex)
{
if (aBuffer[innerIndex] != aSubBuffer[subInnerIndex])
{
isEqual = false;
break;
}
}
if (isEqual)
{
return outerIndex;
}
}
return -1;
}
}
}
我附上了 ActionFilterAttribute,这可能与您相关。
如果您想查看整个代码,可以访问此处: 动态添加样式和脚本
于 2013-02-13T09:03:15.267 回答