2

MVC コントローラーからページのライフサイクルを傍受し、ページまたは DOM のどこかにコードを挿入する方法はありますか? HTML、CSS、および JavaScript をページのヘッダーとフッターに追加したいのですが、アセンブリのどこかに埋め込まれている _Layout ビューには追加しません。SO Global.asax / Application_Start のコントローラーからこれを実行したいと思います。これは可能ですか?

4

1 に答える 1

2

私はそれに似たようなことをしました。

まず、レイアウト ファイル内 (コードを挿入する場所) にプレースホルダーを追加する必要があります。

次に、global.asax にグローバルな ActionFilterAttribute を追加する必要があります。FilterAttribute で、OnActionExecuted のみをフィルター処理し、ViewResults のみをフィルター処理します。

3 番目に、Response.Filter を変更して、html コード内のプレースホルダーを検索し、独自のものに置き換える新しいフィルターを使用する必要があります。

私はまさにそれを書いた、コードのどこにでもスタイルとスクリプトを宣言する方法を追加し、結果が完了すると、リソースが 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 に答える