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

本文源于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中添加过滤器。

  1 public class HtmlScriptStream : MemoryStream
  2     {
  3         private Stream OutputStream { get; set; }
  4         private HttpContext HttpContext { get; set; }
  5         private bool closing;
  6 
  7         public HtmlScriptStream(Stream outputStream, HttpContext httpContext)
  8         {
  9             this.OutputStream = outputStream;
 10             this.HttpContext = httpContext;
 11         }
 12 
 13         public override void Close()
 14         {
 15             // Using a StreamReader to read this will cause Close to be called again
 16             if (this.closing)
 17             {
 18                 return;
 19             }
 20 
 21             this.closing = true;
 22             byte[] buffer = null;
 23             Dictionary<string, string> scripts = HtmlScriptHelper.GetStartupScripts();
 24             if (scripts.Count > 0 
 25                 && this.HttpContext.Response.ContentType == "text/html" 
 26                 && this.HttpContext.Server.GetLastError() == null)
 27             {
 28                 var html = this.ReadOriginalHtml();
 29                 if (!string.IsNullOrEmpty(html))
 30                 {
 31                     string startupScripts = string.Empty;
 32                     foreach (string script in scripts.Values)
 33                     {
 34                         startupScripts += (script + Environment.NewLine);
 35                     }
 36                     if (!string.IsNullOrEmpty(startupScripts))
 37                     {
 38                         int endBodyIndex = html.LastIndexOf("</body>");
 39                         if (endBodyIndex != -1)
 40                         {
 41                             html = html.Insert(endBodyIndex, startupScripts);
 42                         }
 43                     }
 44                 }
 45 
 46                 buffer = this.HttpContext.Response.ContentEncoding.GetBytes(html);
 47 
 48             }
 49             else
 50             {
 51                 this.Position = 0;
 52                 buffer = this.GetBuffer();
 53             }
 54 
 55             this.OutputStream.Write(buffer, 0, buffer.Length);
 56             base.Close();
 57         }
 58 
 59         private string ReadOriginalHtml()
 60         {
 61             var html = string.Empty;
 62             Position = 0;
 63             using (var reader = new StreamReader(this))
 64             {
 65                 html = reader.ReadToEnd();
 66             }
 67 
 68             return html;
 69         }
 70     }
 71 
 72     public class HtmlScriptHelper
 73     {
 74         private const string STARTUP_SCRIPTS = "STARTUP_SCRIPTS";
 75         public static bool IsStartupScriptRegistered(string key)
 76         {
 77             return GetStartupScripts().ContainsKey(key);
 78         }
 79 
 80         public static void RegisterStartupScript(string key, string script)
 81         {
 82             if (!IsStartupScriptRegistered(key))
 83             {
 84                 GetStartupScripts().Add(key, script);
 85             }
 86         }
 87 
 88         internal static Dictionary<string, string> GetStartupScripts()
 89         {
 90             Dictionary<string, string> scripts 
 91                 = HttpContext.Current.Items[STARTUP_SCRIPTS] as Dictionary<string, string>;
 92             if (scripts == null)
 93             {
 94                 scripts = new Dictionary<string, string>();
 95                 HttpContext.Current.Items[STARTUP_SCRIPTS] = scripts;
 96             }
 97 
 98             return scripts;
 99         }
100     }
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using System.Web;
 5 using System.Web.UI;
 6 
 7 namespace ScriptHttpModule
 8 {
 9     public class MyFilter : IHttpModule
10     {
11         public void Dispose()
12         {
13      
14         }
15 
16         public void Init(HttpApplication context)
17         {
18             context.BeginRequest += Context_BeginRequest;
19             context.PreRequestHandlerExecute += Context_PreRequestHandlerExecute;
20         }
21 
22         private void Context_BeginRequest(object sender, EventArgs e)
23         {
24             HttpContext httpContext = HttpContext.Current;
25             string url = httpContext.Request.Url.AbsolutePath;
26             if (!(url.EndsWith(".axd") || url.EndsWith(".ashx")
27                 || url.EndsWith(".aspx") || url.EndsWith(".asmx")))
28             {
29                 httpContext.Response.Filter = new HtmlScriptStream(httpContext.Response.Filter, httpContext);
30             }
31         }
32 
33         private void Context_PreRequestHandlerExecute(object sender, EventArgs e)
34         {
35             HttpApplication application = (HttpApplication)sender;
36             HttpContext context = application.Context;
37             if (context != null)
38             {
39                 string sbScript1 = "<script type=\"text/javascript\">alert('a1');</script>";
40                 string sbScript2 = "<script type=\"text/javascript\">alert('a2');</script>";
41                 string sbScript3 = "<script type=\"text/javascript\">alert('a3');</script>";
42                 Page thisPage = context.CurrentHandler as Page;
43 
44                 if (thisPage != null)
45                 {
46                     Type t = thisPage.GetType();
47 
48                     if (!thisPage.ClientScript.IsStartupScriptRegistered(t, "script-1"))
49                     {
50                         thisPage.ClientScript.RegisterStartupScript(t, "script-1", sbScript1);
51                     }
52                 }
53                 else
54                 {
55                     HtmlScriptHelper.RegisterStartupScript("script-1", sbScript1);
56                     HtmlScriptHelper.RegisterStartupScript("script-1", sbScript2);
57                     HtmlScriptHelper.RegisterStartupScript("script-2", sbScript3);
58                 }
59             }
60         }
61     }
62 }

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

你可能感兴趣的:(MVC模式下如何实现RegisterStartupScript等功能)