MVC模式下如何实现RegisterStartupScript等功能

时间:2023-01-13 05:38:15

本文源于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