在开发过程中经常可以遇到下面几个问题:
1.在web用户控件或页面经常会引入一个外部的javascript或css文件。
先说页面吧,当年我有bbs、在线客服、博客,等一些独立的系统。但突然有一天部门接了一个oa的项目,这个oa中又刚好需要bbs、在线客服、博客这些功能。那么我就在根目录下做三个文件夹分别是bbs、blog和webim。
然后直接把原来的系统放到里面去,做好接口,集成进去。
这样做看起来对网站目录的规划更合理、且这三个系统中在根目录下的文件和文件夹不会起冲突。可在页面上直接引入的js和css文件的虚拟路径就出问题了。然道一个个的去改吗?
再说web用户控,这个问题更普遍。比如有个web用户控中引用了一个css文件,可这个web用户控被好多页面引用,且这些页面有很多都不在同一目录下,然道我们每个页面都去引用一次吗?我觉得这样非常不好,css是这个web控件依赖的一个元素,而不是页面的,为什么css文件要注册到页面上呢?为什么还要受页面的路径影响呢?
当然,像“js/javascript.js”这样的路径肯定是不行。部署的时候实施大哥万一不把你的项目直接建立在网站下,而建立到虚拟目录下,那这个路径就是错的。
其实也不是实施大哥的问题,很多服务器都是有它自己的规则,由不得你。比如,我们那抠门的公司一个服务器上要部署200个网站。哪能让你随便搞啊,他说怎么样就怎么样。
2.在后台代码中注册一段弹出脚本。alert();
这个问题非常有意思,比如,你有个添加页面,添加完了后你alert一句话“添加成功!”,多好啊。
然后你又点了个超链接跳到另外个页面。刚好这个页面有个返回按钮。这个按钮直接用js回退到上一页。
结果一回退到上一页(添加页面),他自动给你弹个“添加成功!”的提示。
当时什么用cookie啊,记时间啊,都想过了。总觉得有点大才小用的感觉。
看到这里的朋友不妨自己先想想,有什么好的解决方法,然后再看下面的代码。
为了解决这两个问题,我是这么做的。
先做个IRegisterScriptClient接口。
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.HtmlControls;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace CE.Components.Base
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 提供客户端脚本注册功能的接口。
/// 分别在CE.HR.Base.PageBase和CE.HR.Base.UserControlBase两个类中实现。
/// </summary>
public interface IRegisterScriptClient
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 使用键和 URL 向 Page 对象注册客户端脚本包含
/// </summary>
/// <param name="key">要注册的客户端脚本包含的键。</param>
/// <param name="url">要注册的客户端脚本包含的 URL。</param>
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#")]
void RegisterClientScriptInclude(string key, string url);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 向 Page 对象注册客户端Css样式包含
/// </summary>
/// <param name="url">要注册的客户端Css样式包含的 URL。</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
void RegisterClientCssStyleInclude(string url);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 向 Page 对象注册客户端脚提示消息。
/// </summary>
/// <param name="msg">要弹出的消息。</param>
void RegisterClientScriptAlertMessage(string msg);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
实现接口RegisterScriptClient.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web.UI;
5
using System.Web.UI.HtmlControls;
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
namespace CE.Components.Base
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
9
class RegisterScriptClient : IRegisterScriptClient
10![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
11![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
private Control control;
13
private const string SCRIPT1 = "var alertMessageGuid = \"";
14![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private const string SCRIPT2 = "\";if (window.name != alertMessageGuid)
{alert(\"";
15
private const string SCRIPT3 = "\");alertMessageGuid = window.name;}";
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
public RegisterScriptClient(Control control)
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
this.control = control;
20
}
21![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
IRegisterScriptClient 成员#region IRegisterScriptClient 成员
23![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
25
/// 使用键和 URL 向 Page 对象注册客户端脚本包含
26
/// </summary>
27
/// <param name="key">要注册的客户端脚本包含的键。</param>
28
/// <param name="url">要注册的客户端脚本包含的 URL。</param>
29
public void RegisterClientScriptInclude(string key, string url)
30![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
31
string clientUrl;
32![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
//把url转换成当前页面在客户端可用的url。
34
clientUrl = control.Page.ResolveUrl(url);
35
ScriptManager.RegisterClientScriptInclude(control, this.GetType(), key, clientUrl);
36
}
37![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
39
/// 向 Page 对象注册客户端Css样式包含
40
/// </summary>
41
/// <param name="url">要注册的客户端Css样式包含的 URL。</param>
42
public void RegisterClientCssStyleInclude(string url)
43![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
44
string clientUrl;
45
HtmlLink link;
46![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
//把url转换成当前页面在客户端可用的url。
48
clientUrl = control.Page.ResolveUrl(url);
49![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
//初始化Css样式表引用链接。
51
link = new HtmlLink();
52
link.Href = clientUrl;
53
link.Attributes.Add("rel", "stylesheet");
54
link.Attributes.Add("type", "text/css");
55
control.Page.Header.Controls.Add(link);
56
}
57![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
59
/// 向 Page 对象注册客户端脚提示消息。
60
/// </summary>
61
/// <param name="msg">要弹出的消息。</param>
62
public void RegisterClientScriptAlertMessage(string msg)
63![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
64
string guid;
65
StringBuilder script;
66![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
67
//生成一个唯一标识这段脚本的guid。
68
guid = Guid.NewGuid().ToString("N");
69![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
70
script = new StringBuilder();
71
script.Append(SCRIPT1);
72
script.Append(guid);
73
script.Append(SCRIPT2);
74
script.Append(msg);
75
script.Append(SCRIPT3);
76![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
77
//注册到前台。
78
ScriptManager.RegisterClientScriptBlock(control, control.GetType(),
79
"ShowMessageHelper", script.ToString(), true);
80
}
81![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
82
#endregion
83![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
84
}
85
}
然后再做个页面和web用户控件的基类。这个是页面基类。
using System;
using System.Web.UI;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace CE.Components.Base
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// HR系统所有页面的基类。
/// </summary>
public class PageBase : Page, IRegisterScriptClient
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private IRegisterScriptClient scriptClient;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public PageBase()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
scriptClient = new RegisterScriptClient(this);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
IRegisterScriptClient 成员#region IRegisterScriptClient 成员
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 使用键和 URL 向 Page 对象注册客户端脚本包含
/// </summary>
/// <param name="key">要注册的客户端脚本包含的键。</param>
/// <param name="url">要注册的客户端脚本包含的 URL。</param>
public void RegisterClientScriptInclude(string key, string url)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
scriptClient.RegisterClientScriptInclude(key, url);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 向 Page 对象注册客户端Css样式包含
/// </summary>
/// <param name="url">要注册的客户端Css样式包含的 URL。</param>
public void RegisterClientCssStyleInclude(string url)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
scriptClient.RegisterClientCssStyleInclude(url);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 向 Page 对象注册客户端脚提示消息。
/// </summary>
/// <param name="msg">要弹出的消息。</param>
public void RegisterClientScriptAlertMessage(string msg)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
scriptClient.RegisterClientScriptAlertMessage(msg);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
这样使用起来就会方便很多。注册脚本或者样式表,可以直接使用应用程序根的虚拟路径。(例如,以“~/page.aspx”的形式)
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
using CE.Components.Base;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public partial class _Default : PageBase
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
protected void Page_Load(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
protected override void OnPreRender(EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
base.OnPreRender(e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//调用框架的基类方法,可以直接使用“应用程序根的虚拟路径”注册js和css文件到页面。
this.RegisterClientCssStyleInclude("~/skin/StandardUI.css");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
还有注册脚本引用和alert脚本,以及在用户控件中的使用我就不啰嗦了,一样的东西。