根据您在问题中所做的编辑,您需要一个 HTTP 模块来修改生成的注入您的脚本的代码。
首先,您需要创建一个派生自 Stream 的类,它将包装来自 Response.Filter 的原始 Stream。
public class GtmStream : Stream
{
private static string gtmScript = @"<!-- Google Tag Manager -->...";
private Stream _base;
public GtmStream(Stream stream)
{
_base = stream;
}
public override void Flush()
{
_base.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _base.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
var editedBuffer = GetByteArrayWithGtmScriptInjected(buffer);
_base.Write(editedBuffer, offset, editedBuffer.Length);
}
public byte[] GetByteArrayWithGtmScriptInjected(byte[] buffer)
{
var stringValue = System.Text.Encoding.UTF8.GetString(buffer);
if (!string.IsNullOrWhiteSpace(stringValue))
{
var position = stringValue.IndexOf("</body>");
if (position != -1)
{
stringValue = stringValue.Insert(position + 7, gtmScript);
}
}
return System.Text.Encoding.UTF8.GetBytes(stringValue.ToCharArray());
}
public override bool CanRead
{
get { throw new NotImplementedException(); }
}
public override bool CanSeek
{
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { throw new NotImplementedException(); }
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotImplementedException(); }
}
public override long Position
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
每次调用方法 Write 时,Stream 都会检查它是否包含标签,如果存在,它将在其后注入脚本代码。
然后它将返回新的字节数组并调用基础 Stream 上的 Write 方法。
要将其插入您的 Web 应用程序,您需要创建一个 HTTP 模块,如下所示:
public class GtmScriptModule : IHttpModule
{
private GtmStream gtmStream;
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
gtmStream = new GtmStream(application.Context.Response.Filter);
application.Context.Response.Filter = gtmStream;
}
public void Dispose()
{
}
}
这只会将 Response.Filter 设置为您的自定义 Stream。
最后,您需要将 HTTP 模块插入 Web 应用程序:
<system.web>
...
<httpModules>
<add name="GtmScriptModule" type="TestMvcApplication.Modules.GtmScriptModule, TestMvcApplication" />
</httpModules>
</system.web>
如果您想深入了解理论,这里有一些有用的链接: