MVC模式下如何实现RegisterStartupScript等功能
本文源于http://www.achtmaal.com/blog/asp-net-mvc-and-registerclientscriptinclude,非常感谢原文作者的智慧和分享
RegisterStartupScript系列的向前台输出脚本的方法,是基于WebForm的,在MVC日益盛行的时代,它则无法正常工作了。但不论出于什么原因,也许你还会需要用到它,至少我有这样的需求。原文的作者提供了一个方法,我这里不作翻译,简单地描述一下工作原理。
- 每一个页面虽然不再是Page对象,用不了Register***功能,但是它仍然在一个HTTP Pipeline里面。
- 每一个页面请求的HttpContext.Current.Items仍然适用,它对每一个请求负责,我们将不同的Script存在里面,并在Http Pipeline的不同EventHandler中进行处理。
- HttpContext.Current.Reponse.Filter可以截获整个页面的流,可以将其中的内容进行改写。
与原文不同,我的代码场景和他不同,所以我做了简化。
- HtmlScriptHelper提供给用户进行调用,目的是向HttpContext.Current.Items中添加Script,调用方法和以前一样。
-
在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 }
下载附件:https://files.cnblogs.com/files/volnet/MvcHtmlScriptTest.rar
posted on 2016-05-25 21:52 volnet(可以叫我大V) 阅读(1227) 评论(0) 编辑 收藏 举报