【问题标题】:Injecting javascript on every page in asp.net在asp.net的每个页面上注入javascript
【发布时间】:2016-01-28 05:28:51
【问题描述】:

我正在网站上实施 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 -->

【问题讨论】:

  • inject 是什么意思? DTM 脚本是 javascript 吗?
  • 请更精确。哪个版本的asp.net?还是 Asp.Net MVC?
  • @DeblatonJean-Philippe 我已经编辑了这个问题。任何帮助将不胜感激:)
  • @HamletHakobyan 是的,它是一个 javascript。我已编辑问题以包含脚本。
  • @vinu 根据您编辑的问题我添加了另一个答案,请查看。

标签: javascript asp.net .net asp.net-mvc iis


【解决方案1】:

根据您在问题中所做的编辑,您需要一个 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>


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

【讨论】:

  • 虽然这可行,但与使用母版页和布局页相比,它是一个不太优雅的解决方案。 @vinu 你应该仔细看看 user449689 的编辑答案。
【解决方案2】:

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

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

【讨论】:

  • thnx.. 但是网站包含来自 MVC 4.0 和 ASP.NET 4.0 的混合内容。请原谅我之前没有提到它。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2017-08-15
    • 2013-01-02
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多