繁体   English   中英

在asp.net的每个页面上注入JavaScript

[英]Injecting javascript on every page in asp.net

我正在网站上实施GTM。 网站上有400多个页面,必须放置GTM脚本。 有什么方法可以在body标签之后的每页上插入GTM脚本? 网站使用混合技术,某些页面在ASP.NET 4.0中,而某些页面在MVC 4.0中。 以下是要添加的示例脚本:

<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-#####"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-#####');</script>
<!-- End Google Tag Manager -->

根据您在问题中所做的编辑,您需要一个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设置为您的自定义流。

最后,您需要将HTTP模块插入Web应用程序:

<system.web>
    ...
    <httpModules>
      <add name="GtmScriptModule" type="TestMvcApplication.Modules.GtmScriptModule, TestMvcApplication" />
    </httpModules>
  </system.web>


如果您想深入了解理论,这里有一些有用的链接:

尝试创建一个将在每个请求上运行的HTTP模块,检查该请求是否针对某个页面,如果是,则将其返回给您的JavaScript块

https://msdn.microsoft.com/en-us/library/vstudio/ms227673(v=vs.100).aspx

对于MVC页面,您应该将脚本放置在Web应用程序的默认布局文件中,然后在_ViewStart.cshtml文件中为每个视图设置布局。

对于您的Web窗体页面,您可以对母版页执行相同操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM