using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using NewLife.Configuration;
using NewLife.Log;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace NewLife.CommonEntity.Web
{
///// <summary>指定具体管理员类和菜单类的页面基类</summary>
///// <typeparam name="TAdminEntity"></typeparam>
///// <typeparam name="TMenuEntity"></typeparam>
//[EditorBrowsable(EditorBrowsableState.Never)]
//[Obsolete("不再需要指定管理员类和菜单类,请改用WebPageBase类替代!")]
//public class WebPageBase<TAdminEntity, TMenuEntity> : WebPageBase<TAdminEntity>
// where TAdminEntity : Administrator<TAdminEntity>, new()
// where TMenuEntity : Menu<TMenuEntity>, new()
//{
//}
///// <summary>指定具体管理员类的页面基类</summary>
///// <typeparam name="TAdminEntity"></typeparam>
//[EditorBrowsable(EditorBrowsableState.Never)]
//[Obsolete("不再需要指定管理员类和菜单类,请改用WebPageBase类替代!")]
//public class WebPageBase<TAdminEntity> : WebPageBase
// where TAdminEntity : Administrator<TAdminEntity>, new()
//{
// /// <summary>当前管理员</summary>
// public override IAdministrator Current
// {
// get
// {
// return Administrator<TAdminEntity>.Current;
// }
// }
//}
/// <summary>页面基类</summary>
public class WebPageBase : System.Web.UI.Page
{
#region 菜单
/// <summary>导航 分为三级:栏目-子栏目-页面</summary>
public virtual String Navigation
{
get
{
if (MyMenu == null) return null;
return MyMenu.GetFullPath(true, " - ", item => String.Format("[{0}]", item.Name));
}
}
private List<String> hasLoaded = new List<String>();
private IMenu _MyMenu;
/// <summary>本页菜单</summary>
public virtual IMenu MyMenu
{
get
{
if (_MyMenu == null && !hasLoaded.Contains("MyMenu"))
{
_MyMenu = ManageProvider.Menu.Root.FindByPath(PermissionName);
hasLoaded.Add("MyMenu");
}
return _MyMenu;
}
set { _MyMenu = value; }
}
#endregion
#region 权限控制
private Boolean _ValidatePermission = true;
/// <summary>是否检查权限</summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("后续版本将不再支持该属性,请重写CheckPermission来判断是否验证授权!")]
public virtual Boolean ValidatePermission
{
get { return _ValidatePermission; }
set { _ValidatePermission = value; }
}
/// <summary>权限名。默认是页面标题</summary>
public virtual String PermissionName
{
get
{
// 默认使用标题
if (!String.IsNullOrEmpty(Title)) return Title;
// 计算 目录/文件 的形式
String p = Request.PhysicalPath;
String dirName = new DirectoryInfo(Path.GetDirectoryName(p)).Name;
String fileName = Path.GetFileNameWithoutExtension(p);
return String.Format(@"{0}/{1}", dirName, fileName);
}
}
/// <summary>检查是否已登录</summary>
/// <returns></returns>
public virtual Boolean CheckLogin()
{
// 当前管理员
var entity = Current;
if (entity == null) return false;
return true;
}
/// <summary>检查权限,实际上就是Acquire(PermissionFlags.None)</summary>
/// <returns></returns>
public virtual Boolean CheckPermission()
{
return Acquire(PermissionFlags.None);
}
/// <summary>申请指定操作的权限</summary>
/// <param name="flag"></param>
/// <returns></returns>
public virtual Boolean Acquire(PermissionFlags flag)
{
// 当前管理员
var admin = Current;
if (admin == null) return false;
var menu = MyMenu;
//if (menu == null)
//{
// String name = PermissionName;
// if (String.IsNullOrEmpty(name)) return false;
// // 当前权限菜单
// menu = admin.FindPermissionMenu(name);
//}
if (menu == null) return false;
return admin.Role.Has(menu.ID, flag);
}
/// <summary>申请指定操作的权限</summary>
/// <param name="name">名称</param>
/// <param name="flag"></param>
/// <returns></returns>
public virtual Boolean Acquire(String name, PermissionFlags flag)
{
// 当前管理员
var admin = Current;
if (admin == null) return false;
//IMenu menu = admin.FindPermissionMenu(name);
//if (menu == null) return false;
//return admin.Acquire(menu.ID, flag);
var mi = ManageProvider.Menu.Root.FindByPath(name);
if (mi == null) return false;
return admin.Role.Has(mi.ID, flag);
}
/// <summary>申请指定操作的权限</summary>
/// <param name="name">名称</param>
/// <returns></returns>
public virtual Boolean Acquire(String name)
{
return Acquire(name, PermissionFlags.None);
}
#endregion
#region 登录用户控制
/// <summary>当前管理员</summary>
public virtual IUser Current
{
get
{
return ManageProvider.Provider.Current as IUser;
}
}
/// <summary>已重载。</summary>
/// <param name="e"></param>
protected override void OnPreLoad(EventArgs e)
{
CheckStarting();
base.OnPreLoad(e);
try
{
if (!CheckLogin())
{
Response.StatusCode = 403;
Response.StatusDescription = "没有登录!";
Response.Write("没有登录!");
Response.End();
}
else if (!CheckPermission())
{
Response.StatusCode = 403;
//Response.SubStatusCode = 15;
Response.StatusDescription = "没有权限访问该页!";
Response.Write("没有权限访问该页!");
Response.End();
}
}
catch (ThreadAbortException) { }
catch (Exception ex)
{
XTrace.WriteException(ex);
}
}
#endregion
#region 运行时输出
private Int32 StartQueryTimes = DAL.QueryTimes;
private Int32 StartExecuteTimes = DAL.ExecuteTimes;
/// <summary>是否输出执行时间</summary>
[Obsolete("后续版本将不再支持该属性,请重写CheckPermission来判断是否验证授权!")]
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual Boolean IsWriteRunTime
{
get
{
if (!Request.PhysicalPath.EndsWithIgnoreCase(".aspx")) return false;
return XTrace.Debug;
}
}
/// <summary>执行时间字符串</summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("后续版本将不再支持该属性,请重写CheckPermission来判断是否验证授权!")]
protected virtual String RunTimeString { get { return "查询{0}次,执行{1}次,耗时{2}毫秒!"; } }
/// <summary></summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)
{
Literal lt = FindControl("RunTime") as Literal;
if (lt != null) WriteRunTime();
base.Render(writer);
if (lt == null) WriteRunTime();
}
/// <summary>输出运行时间</summary>
protected virtual void WriteRunTime()
{
if (!Request.PhysicalPath.EndsWithIgnoreCase(".aspx")) return;
if (!XTrace.Debug) return;
//判断是否为Ajax 异步请求,以排除“Sys.WebForms.PageRequestManagerParserErrorException: 未能分析从服务器收到的消息 ”异常
if (Request.Headers["X-MicrosoftAjax"] != null || Request.Headers["x-requested-with"] != null) return;
TimeSpan ts = DateTime.Now - HttpContext.Current.Timestamp;
String str = String.Format("查询{0}次,执行{1}次,耗时{2}毫秒!", DAL.QueryTimes - StartQueryTimes, DAL.ExecuteTimes - StartExecuteTimes, ts.TotalMilliseconds);
Literal lt = FindControl("RunTime") as Literal;
if (lt != null)
lt.Text = str;
else
Response.Write(str);
}
#endregion
#region 压缩ViewState
/// <summary>设定序列化后的字符串长度为多少后启用压缩</summary>
private static Int32 LimitLength = 1096;
/// <summary>是否压缩ViewState</summary>
protected virtual Boolean CompressViewState { get { return Config.GetConfig<Boolean>("NewLife.CommonEntity.CompressViewState", true); } }
/// <summary>重写保存页的所有视图状态信息</summary>
/// <param name="state">要在其中存储视图状态信息的对象</param>
protected override void SavePageStateToPersistenceMedium(Object state)
{
if (!CompressViewState)
{
base.SavePageStateToPersistenceMedium(state);
return;
}
MemoryStream ms = new MemoryStream();
new LosFormatter().Serialize(ms, state);
String vs = null;
//判断序列化对象的字符串长度是否超出定义的长度界限
if (ms.Length > LimitLength)
{
MemoryStream ms2 = new MemoryStream();
// 必须移到第一位,否则后面读不到数据
ms.Position = 0;
IOHelper.Compress(ms, ms2);
vs = "1$" + Convert.ToBase64String(ms2.ToArray());
}
else
vs = Convert.ToBase64String(ms.ToArray());
//注册在页面储存ViewState状态的隐藏文本框,并将内容写入这个文本框
ClientScript.RegisterHiddenField("__VSTATE", vs);
}
/// <summary>重写将所有保存的视图状态信息加载到页面对象</summary>
/// <returns>保存的视图状态</returns>
protected override Object LoadPageStateFromPersistenceMedium()
{
if (!CompressViewState) return base.LoadPageStateFromPersistenceMedium();
//使用Request方法获取序列化的ViewState字符串
String vs = Request.Form.Get("__VSTATE");
Byte[] bts = null;
if (vs.StartsWith("1$"))
bts = IOHelper.Decompress(Convert.FromBase64String(vs.Substring(2)));
else
bts = Convert.FromBase64String(vs);
//将指定的视图状态值转换为有限对象序列化 (LOS) 格式化的对象
return new LosFormatter().Deserialize(new MemoryStream(bts));
}
#endregion
#region 系统启动中
static Boolean SystemStarted = false;
/// <summary>检查系统是否启动中,如果启动中,则显示进度条</summary>
public static void CheckStarting()
{
if (HttpContext.Current == null) return;
HttpRequest Request = HttpContext.Current.Request;
HttpResponse Response = HttpContext.Current.Response;
// 在用Flush前用一次Session,避免可能出现的问题
String sessionid = HttpContext.Current.Session.SessionID;
// 只处理GET,因为处理POST可能丢失提交的表单数据
if (Request.HttpMethod != "GET") return;
if (SystemStarted) return;
SystemStarted = true;
#region 输出脚本
StringBuilder sb = new StringBuilder();
sb.Append(@"<html><head>
<script language=""javascript"" type=""text/javascript"">
var t_id = setInterval(animate,20);
var pos=0;var dir=2;var len=0;
function animate(){
var elem = document.getElementById('progress');
if(elem != null) {
if (pos==0) len += dir;
if (len>32 || pos>79) pos += dir;
if (pos>79) len -= dir;
if (pos>79 && len==0) pos=0;
elem.style.left = pos;
elem.style.width = len;
}
}
function stopAnimate(){
clearInterval(t_id);
var elem = document.getElementById('loader_container');
elem.style.display='none';
}
</script>
<style>
#loader_container {text-align:center; position:absolute; top:40%; width:100%; left: 0;}
#loader {font-family:Tahoma, Helvetica, sans; font-size:11.5px; color:#000000; background-color:#FFFFFF; padding:10px 0 16px 0; margin:0 auto; display:block; width:130px; border:1px solid #5a667b; text-align:left; z-index:2;}
#progress {height:5px; font-size:1px; width:1px; position:relative; top:1px; left:0px; background-color:#8894a8;}
#loader_bg {background-color:#e4e7eb; position:relative; top:8px; left:8px; height:7px; width:113px; font-size:1px;}
</style>
</head><body>
<div id=loader_container>
<div id=loader>
<div align=center>系统正在启动中 ...</div>
<div id=loader_bg><div id=progress> </div></div>
</div>
</div>
<div style=""position:absolute; left:1em; top:1em; width:320px; padding:.3em; background:#900; color:#fff; display:none;"">
<strong>系统启动发生异常</strong>
<div id=""start_fail""></div>
</div>
<script type=""text/javascript"" language=""javascript"">
(function(w){
var xhr;
if(w.XMLHttpRequest && !w.ActiveXObject){
xhr=new w.XMLHttpRequest();
}else{
try{
xhr=new w.ActiveXObject('Microsoft.XMLHTTP');
}catch(e){}
}
if(xhr){
xhr.open('GET','?ajax=1');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
//只有返回http 200时才表示正常
if(xhr.status===200){
xhr=null;
location.reload();
}else{
//否则输出http状态码和状态说明,以及返回的html
stopAnimate();
var ele=document.getElementById('start_fail');
ele.innerHTML='HTTP '+xhr.status+' '+xhr.statusText+'<br/>'+xhr.responseText;
var par=ele.parentNode;
if(par){
par.style.display='block';
}
}
xhr=null;
}
};
xhr.send();
}else{
// 不支持的浏览器将直接刷新 不再显示动画
location.reload();
}
})(window);
</script>
</body></html>");
//还可以选择使用<script src="?script=1" type="text/javascript"></script>的方式 只是对返回内容有要求
//sb.AppendLine("function remove_loading() {");
//sb.AppendLine(" this.clearInterval(t_id);");
//sb.AppendLine("var targelem = document.getElementById('loader_container');");
//sb.AppendLine("targelem.style.display='none';");
//sb.AppendLine("targelem.style.visibility='hidden';");
//sb.AppendLine("}");
//sb.AppendLine("document.onload=function(){ location.reload(); }");
//sb.AppendLine("document.onload=remove_loading;");
if (!Response.IsClientConnected) return;
Response.Write(sb.ToString());
Response.Flush();
Response.End();
#endregion
}
#endregion
}
}
|