本文源于http://www.achtmaal.com/blog/asp-net-mvc-and-registerclientscriptinclude,非常感谢原文作者的智慧和分享

RegisterStartupScript系列的向前台输出脚本的方法,是基于WebForm的,在MVC日益盛行的时代,它则无法正常工作了。但不论出于什么原因,也许你还会需要用到它,至少我有这样的需求。原文的作者提供了一个方法,我这里不作翻译,简单地描述一下工作原理。

  1. 每一个页面虽然不再是Page对象,用不了Register***功能,但是它仍然在一个HTTP Pipeline里面。
  2. 每一个页面请求的HttpContext.Current.Items仍然适用,它对每一个请求负责,我们将不同的Script存在里面,并在Http Pipeline的不同EventHandler中进行处理。
  3. HttpContext.Current.Reponse.Filter可以截获整个页面的流,可以将其中的内容进行改写。

与原文不同,我的代码场景和他不同,所以我做了简化。

  1. HtmlScriptHelper提供给用户进行调用,目的是向HttpContext.Current.Items中添加Script,调用方法和以前一样。
  2. 在context.BeginRequest += Context_BeginRequest;处理程序中,向HttpContext.Current.Reponse.Filter中添加过滤器。

 public class HtmlScriptStream : MemoryStream
{
private Stream OutputStream { get; set; }
private HttpContext HttpContext { get; set; }
private bool closing; public HtmlScriptStream(Stream outputStream, HttpContext httpContext)
{
this.OutputStream = outputStream;
this.HttpContext = httpContext;
} public override void Close()
{
// Using a StreamReader to read this will cause Close to be called again
if (this.closing)
{
return;
} this.closing = true;
byte[] buffer = null;
Dictionary<string, string> scripts = HtmlScriptHelper.GetStartupScripts();
if (scripts.Count >
&& this.HttpContext.Response.ContentType == "text/html"
&& this.HttpContext.Server.GetLastError() == null)
{
var html = this.ReadOriginalHtml();
if (!string.IsNullOrEmpty(html))
{
string startupScripts = string.Empty;
foreach (string script in scripts.Values)
{
startupScripts += (script + Environment.NewLine);
}
if (!string.IsNullOrEmpty(startupScripts))
{
int endBodyIndex = html.LastIndexOf("</body>");
if (endBodyIndex != -)
{
html = html.Insert(endBodyIndex, startupScripts);
}
}
} buffer = this.HttpContext.Response.ContentEncoding.GetBytes(html); }
else
{
this.Position = ;
buffer = this.GetBuffer();
} this.OutputStream.Write(buffer, , buffer.Length);
base.Close();
} private string ReadOriginalHtml()
{
var html = string.Empty;
Position = ;
using (var reader = new StreamReader(this))
{
html = reader.ReadToEnd();
} return html;
}
} public class HtmlScriptHelper
{
private const string STARTUP_SCRIPTS = "STARTUP_SCRIPTS";
public static bool IsStartupScriptRegistered(string key)
{
return GetStartupScripts().ContainsKey(key);
} public static void RegisterStartupScript(string key, string script)
{
if (!IsStartupScriptRegistered(key))
{
GetStartupScripts().Add(key, script);
}
} internal static Dictionary<string, string> GetStartupScripts()
{
Dictionary<string, string> scripts
= HttpContext.Current.Items[STARTUP_SCRIPTS] as Dictionary<string, string>;
if (scripts == null)
{
scripts = new Dictionary<string, string>();
HttpContext.Current.Items[STARTUP_SCRIPTS] = scripts;
} return scripts;
}
}
 using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI; namespace ScriptHttpModule
{
public class MyFilter : IHttpModule
{
public void Dispose()
{ } public void Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
context.PreRequestHandlerExecute += Context_PreRequestHandlerExecute;
} private void Context_BeginRequest(object sender, EventArgs e)
{
HttpContext httpContext = HttpContext.Current;
string url = httpContext.Request.Url.AbsolutePath;
if (!(url.EndsWith(".axd") || url.EndsWith(".ashx")
|| url.EndsWith(".aspx") || url.EndsWith(".asmx")))
{
httpContext.Response.Filter = new HtmlScriptStream(httpContext.Response.Filter, httpContext);
}
} private void Context_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
if (context != null)
{
string sbScript1 = "<script type=\"text/javascript\">alert('a1');</script>";
string sbScript2 = "<script type=\"text/javascript\">alert('a2');</script>";
string sbScript3 = "<script type=\"text/javascript\">alert('a3');</script>";
Page thisPage = context.CurrentHandler as Page; if (thisPage != null)
{
Type t = thisPage.GetType(); if (!thisPage.ClientScript.IsStartupScriptRegistered(t, "script-1"))
{
thisPage.ClientScript.RegisterStartupScript(t, "script-1", sbScript1);
}
}
else
{
HtmlScriptHelper.RegisterStartupScript("script-1", sbScript1);
HtmlScriptHelper.RegisterStartupScript("script-1", sbScript2);
HtmlScriptHelper.RegisterStartupScript("script-2", sbScript3);
}
}
}
}
}

下载附件:http://files.cnblogs.com/files/volnet/MvcHtmlScriptTest.rar

MVC模式下如何实现RegisterStartupScript等功能的更多相关文章

  1. MongoDB学习笔记(三) 在MVC模式下通过Jqgrid表格操作MongoDB数据

    看到下图,是通过Jqgrid实现表格数据的基本增删查改的操作.表格数据增删改是一般企业应用系统开发的常见功能,不过不同的是这个表格数据来源是非关系型的数据库MongoDB.nosql虽然概念新颖,但是 ...

  2. 【案例分享】使用ActiveReports报表工具,在.NET MVC模式下动态创建报表

    提起报表,大家会觉得即熟悉又陌生,好像常常在工作中使用,又似乎无法准确描述报表.今天我们来一起了解一下什么是报表,报表的结构.构成元素,以及为什么需要报表. 什么是报表 简单的说:报表就是通过表格.图 ...

  3. 在MVC模式下通过Jqgrid表格操作MongoDB数据

    看到下图,是通过Jqgrid实现表格数据的基本增删查改的操作.表格数据增删改是一般企业应用系统开发的常见功能,不过不同的是这个表格数据来源是非关系型的数据库MongoDB.nosql虽然概念新颖,但是 ...

  4. MVC模式下My97DatePicker日期控件引用注意事项

    My97DatePicker日期控件之前在用webform模式开发的时候,只要 <script language="javascript" type="text/j ...

  5. 卡卡游戏引擎之MVC模式下的事件处理

    前言 在前一篇文章 卡卡游戏引擎快速入门中提到了卡卡游戏引擎采用mvc的开发模式,这里相信介绍一下引擎在mvc模式下是如何做到低耦合的事件处理的. 在卡卡编辑器中选择一个节点,然后在左侧工具栏中切换到 ...

  6. Android:MVC模式(下)

    在上一篇文章中,我们将 View 类单独出来并完成了设计和编写.这次我们将完成 Model 类,并通过 Controller 将两者连接起来,完成这个计算器程序. 模型(Model)就是程序中封装了数 ...

  7. 编码风格:Mvc模式下SSM环境,代码分层管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.分层策略 MVC模式与代码分层策略,MVC全名是ModelViewController即模型-视图-控制器,作为一种软件设计典范,用一种业 ...

  8. MVC模式下unity配置,报错“No connection string named '**Context' could be found in the application config file”

     写在前面: 第一次配置时好好的,后来第二次改到MVC模式,把依赖注入写成字典的单例模式时,由于新建的ORM(数据库映射模型EF),怎么弄都不用,一直报错"No connection str ...

  9. MVC模式下xml文件的解析

    第一次写blog,组织不当和出错的地方还请大家多担当哈. java操作xml文件的方式中用的较多的有四种,DOM.SAX.JDOM.DOM4J.除第一种外其余的三种我都有试过,这后三种方案中我选择用S ...

随机推荐

  1. RedHat 6.7 Enterprise x64环境下使用RHCS部署Oracle 11g R2双机HA

    环境 软硬件环境 硬件环境: 浪潮英信服务器NF570M3两台,华为OceanStor 18500存储一台,以太网交换机两台,光纤交换机两台. 软件环境: 操作系统:Redhat Enterprise ...

  2. Android Studio线下版和线上版都使用正式签名脚本(保证keysore签名文件和项目在同级目录),不用再因为繁琐的发正式版而烦恼

    场景:调用微信等第三方应用时如果生成的版本不是正式签名的可能会调用失败,使用如下脚本不用再为繁琐的发正式签名版而烦恼 app项目中的build.gradle追加如下代码: //使用正式签名脚本(保证k ...

  3. colorbox 自适应 高度

    $(".example3").colorbox({  inline: true, scrolling: false ,                    onComplete: ...

  4. Spring SpringMVC和Mybatis整合

    1.引入所要的jar包 2.创建Mybatis的sqlMapConfig.xml配置文件,该文件中可以配置mybaits的相关参数,数据源不在这里配置. <?xml version=" ...

  5. 向modesim中添加alter库 (或者在每次仿真时将库文件加入仿真文件夹一起编译)

    在ModelSim中进行仿真需要加入Quartus提供的仿真库,原因是下面三个方面:    ·Quartus不支持Testbench:    ·调用了megafunction或者lpm库之类的Alte ...

  6. 如何将C++代码逆向生成类图 (VS2013)

    1. 将代码添加到VS2013工程中: 2. 切换到"类视图": 3. 选中项目 右键"视图"->"查看类图". 如果项目文件太多的话 ...

  7. VMware Linux Guest 增加磁盘无需重启的方法

    摘要     常常需要需要给VMware Linux Guest增加磁盘适配一些测试场景,而又不想花费时间重启Guest,查找文档,发现一种简单的方法,记录一下操作步骤. 操作步骤 1 编辑Linux ...

  8. (转)__cdecl __fastcall与 __stdcall

    原帖 http://blog.sina.com.cn/s/blog_6b7c56870100l8rf.html __cdecl   __fastcall与   __stdcall 调用约定:  __c ...

  9. Maven插件之maven-archetype-plugin

    Maven插件之maven-archetype-plugin 时间:2014-03-29 学过Maven的人,都知道用MyEclipse的Maven插件生成一个项目骨架,比如maven-archety ...

  10. Git常用

    创建本地库 mkdir [dirname] cd [dirname] git init 1.创建项目目录 2.进入目录 3.git初始化 [dirname]为自己取的文件夹名字,例如mkdir myd ...