PageRenderTime 25ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/V8Demo/NewLife.CommonEntity/Web/WebPageBase.cs

#
C# | 595 lines | 321 code | 72 blank | 202 comment | 39 complexity | bc0b60df41fc8aaedadcb872dc89890c MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Security.Principal;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Web;
  8. using System.Web.UI;
  9. using System.Web.UI.WebControls;
  10. using NewLife.Configuration;
  11. using NewLife.IO;
  12. using NewLife.Log;
  13. using XCode.DataAccessLayer;
  14. namespace NewLife.CommonEntity.Web
  15. {
  16. ///// <summary>
  17. ///// 页面基类
  18. ///// </summary>
  19. //public class WebPageBase : WebPageBase<Administrator, Menu> { }
  20. /// <summary>
  21. /// 指定具体管理员类和菜单类的页面基类
  22. /// </summary>
  23. /// <typeparam name="TAdminEntity"></typeparam>
  24. /// <typeparam name="TMenuEntity"></typeparam>
  25. [Obsolete("不再需要指定管理员类和菜单类,请改用WebPageBase类替代!")]
  26. public class WebPageBase<TAdminEntity, TMenuEntity> : WebPageBase<TAdminEntity>
  27. where TAdminEntity : Administrator<TAdminEntity>, new()
  28. where TMenuEntity : Menu<TMenuEntity>, new()
  29. {
  30. //#region 菜单
  31. ///// <summary>
  32. ///// 导航 分为三级:栏目-子栏目-页面
  33. ///// </summary>
  34. //public virtual String Navigation
  35. //{
  36. // get
  37. // {
  38. // if (MyMenu == null) return null;
  39. // // 无限路径
  40. // EntityList<TMenuEntity> list = MyMenu.GetFullPath(true);
  41. // //StringBuilder sb = new StringBuilder();
  42. // //foreach (TMenuEntity item in list)
  43. // //{
  44. // // if (sb.Length > 0) sb.Append(" - ");
  45. // // sb.AppendFormat("[{0}]", item.Name);
  46. // //}
  47. // //return sb.ToString();
  48. // return MyMenu.GetFullPath(true, " - ", delegate(TMenuEntity item)
  49. // {
  50. // return String.Format("[{0}]", item.Name);
  51. // });
  52. // }
  53. //}
  54. //private List<String> hasLoaded = new List<String>();
  55. //private TMenuEntity _MyMenu;
  56. ///// <summary>本页菜单</summary>
  57. //public virtual TMenuEntity MyMenu
  58. //{
  59. // get
  60. // {
  61. // if (_MyMenu == null && !hasLoaded.Contains("MyMenu"))
  62. // {
  63. // _MyMenu = Menu<TMenuEntity>.FindForPerssion(PermissionName);
  64. // if (_MyMenu == null) _MyMenu = Menu<TMenuEntity>.Current;
  65. // hasLoaded.Add("MyMenu");
  66. // }
  67. // return _MyMenu;
  68. // }
  69. // set { _MyMenu = value; }
  70. //}
  71. //#endregion
  72. //#region 权限控制
  73. ///// <summary>
  74. ///// 申请指定操作的权限
  75. ///// </summary>
  76. ///// <param name="flag"></param>
  77. ///// <returns></returns>
  78. //public override Boolean Acquire(PermissionFlags flag)
  79. //{
  80. // if (MyMenu == null) return base.Acquire(flag);
  81. // // 当前管理员
  82. // IAdministrator entity = Current;
  83. // if (entity == null) return false;
  84. // return entity.Acquire(MyMenu.ID, flag);
  85. //}
  86. //#endregion
  87. }
  88. /// <summary>
  89. /// 指定具体管理员类的页面基类
  90. /// </summary>
  91. /// <typeparam name="TAdminEntity"></typeparam>
  92. [Obsolete("不再需要指定管理员类和菜单类,请改用WebPageBase类替代!")]
  93. public class WebPageBase<TAdminEntity> : WebPageBase
  94. where TAdminEntity : Administrator<TAdminEntity>, new()
  95. {
  96. /// <summary>
  97. /// 当前管理员
  98. /// </summary>
  99. public override IAdministrator Current
  100. {
  101. get
  102. {
  103. return Administrator<TAdminEntity>.Current;
  104. }
  105. }
  106. }
  107. /// <summary>
  108. /// 页面基类
  109. /// </summary>
  110. public class WebPageBase : System.Web.UI.Page
  111. {
  112. #region 菜单
  113. /// <summary>
  114. /// 导航 分为三级:栏目-子栏目-页面
  115. /// </summary>
  116. public virtual String Navigation
  117. {
  118. get
  119. {
  120. if (MyMenu == null) return null;
  121. // 无限路径
  122. //EntityList<TMenuEntity> list = MyMenu.GetFullPath(true);
  123. //StringBuilder sb = new StringBuilder();
  124. //foreach (TMenuEntity item in list)
  125. //{
  126. // if (sb.Length > 0) sb.Append(" - ");
  127. // sb.AppendFormat("[{0}]", item.Name);
  128. //}
  129. //return sb.ToString();
  130. return MyMenu.GetFullPath(true, " - ", delegate(IMenu item)
  131. {
  132. return String.Format("[{0}]", item.Name);
  133. });
  134. }
  135. }
  136. private List<String> hasLoaded = new List<String>();
  137. private IMenu _MyMenu;
  138. /// <summary>本页菜单</summary>
  139. public virtual IMenu MyMenu
  140. {
  141. get
  142. {
  143. if (_MyMenu == null && !hasLoaded.Contains("MyMenu"))
  144. {
  145. //_MyMenu = Menu<TMenuEntity>.FindForPerssion(PermissionName);
  146. //_MyMenu = EntityShip.Invoke<IMenu>("FindForPerssion", PermissionName) as IMenu;
  147. _MyMenu = Current.FindPermissionMenu(PermissionName);
  148. //if (_MyMenu == null) _MyMenu = Menu.CurrentMenu;
  149. hasLoaded.Add("MyMenu");
  150. }
  151. return _MyMenu;
  152. }
  153. set { _MyMenu = value; }
  154. }
  155. #endregion
  156. #region 权限控制
  157. private Boolean _ValidatePermission = true;
  158. /// <summary>是否检查权限</summary>
  159. [Obsolete("后续版本将不再支持该属性,请重写CheckPermission来判断是否验证授权!")]
  160. public virtual Boolean ValidatePermission
  161. {
  162. get { return _ValidatePermission; }
  163. set { _ValidatePermission = value; }
  164. }
  165. /// <summary>
  166. /// 权限名。默认是页面标题
  167. /// </summary>
  168. public virtual String PermissionName
  169. {
  170. get
  171. {
  172. // 默认使用标题
  173. if (!String.IsNullOrEmpty(Title)) return Title;
  174. // 计算 目录/文件 的形式
  175. String p = Request.PhysicalPath;
  176. String dirName = new DirectoryInfo(Path.GetDirectoryName(p)).Name;
  177. String fileName = Path.GetFileNameWithoutExtension(p);
  178. return String.Format(@"{0}/{1}", dirName, fileName);
  179. }
  180. }
  181. /// <summary>
  182. /// 检查是否已登录
  183. /// </summary>
  184. /// <returns></returns>
  185. public virtual Boolean CheckLogin()
  186. {
  187. // 当前管理员
  188. IAdministrator entity = Current;
  189. if (entity == null) return false;
  190. return true;
  191. }
  192. /// <summary>
  193. /// 检查权限,实际上就是Acquire(PermissionFlags.None)
  194. /// </summary>
  195. /// <returns></returns>
  196. public virtual Boolean CheckPermission()
  197. {
  198. return Acquire(PermissionFlags.None);
  199. }
  200. /// <summary>
  201. /// 申请指定操作的权限
  202. /// </summary>
  203. /// <param name="flag"></param>
  204. /// <returns></returns>
  205. public virtual Boolean Acquire(PermissionFlags flag)
  206. {
  207. // 当前管理员
  208. IAdministrator admin = Current;
  209. if (admin == null) return false;
  210. IMenu menu = MyMenu;
  211. //if (menu == null)
  212. //{
  213. // String name = PermissionName;
  214. // if (String.IsNullOrEmpty(name)) return false;
  215. // // 当前权限菜单
  216. // menu = admin.FindPermissionMenu(name);
  217. //}
  218. if (menu == null) return false;
  219. return admin.Acquire(menu.ID, flag);
  220. }
  221. /// <summary>
  222. /// 申请指定操作的权限
  223. /// </summary>
  224. /// <param name="name"></param>
  225. /// <param name="flag"></param>
  226. /// <returns></returns>
  227. public virtual Boolean Acquire(String name, PermissionFlags flag)
  228. {
  229. // 当前管理员
  230. IAdministrator admin = Current;
  231. if (admin == null) return false;
  232. //IMenu menu = admin.FindPermissionMenu(name);
  233. //if (menu == null) return false;
  234. //return admin.Acquire(menu.ID, flag);
  235. return admin.Acquire(name, flag);
  236. }
  237. /// <summary>
  238. /// 申请指定操作的权限
  239. /// </summary>
  240. /// <param name="name"></param>
  241. /// <returns></returns>
  242. public virtual Boolean Acquire(String name)
  243. {
  244. return Acquire(name, PermissionFlags.None);
  245. }
  246. #endregion
  247. #region 登录用户控制
  248. ///// <summary>
  249. ///// Http状态,名称必须和管理员类中一致
  250. ///// </summary>
  251. //static HttpState<IAdministrator> http = new HttpState<IAdministrator>("Admin");
  252. /// <summary>
  253. /// 当前管理员
  254. /// </summary>
  255. public virtual IAdministrator Current
  256. {
  257. get
  258. {
  259. //return http == null ? null : http.Current;
  260. //return (IAdministrator)Thread.CurrentPrincipal;
  261. return Administrator.CurrentAdministrator;
  262. }
  263. }
  264. /// <summary>
  265. /// 已重载。
  266. /// </summary>
  267. /// <param name="e"></param>
  268. protected override void OnPreLoad(EventArgs e)
  269. {
  270. CheckStarting();
  271. //Thread.CurrentPrincipal = (IPrincipal)Current;
  272. ////Thread.CurrentPrincipal = (IPrincipal)http.Current;
  273. //Unload += new EventHandler(WebPageBase_Unload);
  274. base.OnPreLoad(e);
  275. try
  276. {
  277. if (!CheckLogin())
  278. {
  279. Response.StatusCode = 403;
  280. Response.StatusDescription = "没有登录!";
  281. Response.Write("没有登录!");
  282. Response.End();
  283. }
  284. else if (!CheckPermission())
  285. {
  286. Response.StatusCode = 403;
  287. //Response.SubStatusCode = 15;
  288. Response.StatusDescription = "没有权限访问该页!";
  289. Response.Write("没有权限访问该页!");
  290. Response.End();
  291. }
  292. }
  293. catch (ThreadAbortException) { }
  294. catch (Exception ex)
  295. {
  296. XTrace.WriteLine(ex.ToString());
  297. }
  298. }
  299. //void WebPageBase_Unload(object sender, EventArgs e)
  300. //{
  301. // Thread.CurrentPrincipal = null;
  302. //}
  303. #endregion
  304. #region 运行时输出
  305. private Int32 StartQueryTimes = DAL.QueryTimes;
  306. private Int32 StartExecuteTimes = DAL.ExecuteTimes;
  307. /// <summary>
  308. /// 是否输出执行时间
  309. /// </summary>
  310. [Obsolete("后续版本将不再支持该属性,请重写CheckPermission来判断是否验证授权!")]
  311. protected virtual Boolean IsWriteRunTime
  312. {
  313. get
  314. {
  315. if (!Request.PhysicalPath.EndsWith(".aspx", StringComparison.Ordinal)) return false;
  316. return XTrace.Debug;
  317. }
  318. }
  319. /// <summary>
  320. /// 执行时间字符串
  321. /// </summary>
  322. [Obsolete("后续版本将不再支持该属性,请重写CheckPermission来判断是否验证授权!")]
  323. protected virtual String RunTimeString { get { return "查询{0}次,执行{1}次,耗时{2}毫秒!"; } }
  324. /// <summary>
  325. ///
  326. /// </summary>
  327. /// <param name="writer"></param>
  328. protected override void Render(HtmlTextWriter writer)
  329. {
  330. Literal lt = FindControl("RunTime") as Literal;
  331. if (lt != null) WriteRunTime();
  332. base.Render(writer);
  333. if (lt == null) WriteRunTime();
  334. }
  335. /// <summary>
  336. /// 输出运行时间
  337. /// </summary>
  338. protected virtual void WriteRunTime()
  339. {
  340. if (!Request.PhysicalPath.EndsWith(".aspx", StringComparison.Ordinal)) return;
  341. if (!XTrace.Debug) return;
  342. //判断是否为Ajax 异步请求,以排除“Sys.WebForms.PageRequestManagerParserErrorException: 未能分析从服务器收到的消息 ”异常
  343. if (Request.Headers["X-MicrosoftAjax"] != null || Request.Headers["x-requested-with"] != null) return;
  344. TimeSpan ts = DateTime.Now - HttpContext.Current.Timestamp;
  345. String str = String.Format("查询{0}次,执行{1}次,耗时{2}毫秒!", DAL.QueryTimes - StartQueryTimes, DAL.ExecuteTimes - StartExecuteTimes, ts.TotalMilliseconds);
  346. Literal lt = FindControl("RunTime") as Literal;
  347. if (lt != null)
  348. lt.Text = str;
  349. else
  350. Response.Write(str);
  351. }
  352. #endregion
  353. #region 压缩ViewState
  354. /// <summary>
  355. /// 设定序列化后的字符串长度为多少后启用压缩
  356. /// </summary>
  357. private static Int32 LimitLength = 1096;
  358. /// <summary>
  359. /// 是否压缩ViewState
  360. /// </summary>
  361. protected virtual Boolean CompressViewState { get { return Config.GetConfig<Boolean>("NewLife.CommonEntity.CompressViewState", true); } }
  362. /// <summary>
  363. /// 重写保存页的所有视图状态信息
  364. /// </summary>
  365. /// <param name="state">要在其中存储视图状态信息的对象</param>
  366. protected override void SavePageStateToPersistenceMedium(Object state)
  367. {
  368. if (!CompressViewState)
  369. {
  370. base.SavePageStateToPersistenceMedium(state);
  371. return;
  372. }
  373. MemoryStream ms = new MemoryStream();
  374. new LosFormatter().Serialize(ms, state);
  375. String vs = null;
  376. //判断序列化对象的字符串长度是否超出定义的长度界限
  377. if (ms.Length > LimitLength)
  378. {
  379. MemoryStream ms2 = new MemoryStream();
  380. // 必须移到第一位,否则后面读不到数据
  381. ms.Position = 0;
  382. IOHelper.Compress(ms, ms2);
  383. vs = "1$" + Convert.ToBase64String(ms2.ToArray());
  384. }
  385. else
  386. vs = Convert.ToBase64String(ms.ToArray());
  387. //注册在页面储存ViewState状态的隐藏文本框,并将内容写入这个文本框
  388. ClientScript.RegisterHiddenField("__VSTATE", vs);
  389. }
  390. /// <summary>
  391. /// 重写将所有保存的视图状态信息加载到页面对象
  392. /// </summary>
  393. /// <returns>保存的视图状态</returns>
  394. protected override Object LoadPageStateFromPersistenceMedium()
  395. {
  396. if (!CompressViewState) return base.LoadPageStateFromPersistenceMedium();
  397. //使用Request方法获取序列化的ViewState字符串
  398. String vs = Request.Form.Get("__VSTATE");
  399. Byte[] bts = null;
  400. if (vs.StartsWith("1$"))
  401. bts = IOHelper.Decompress(Convert.FromBase64String(vs.Substring(2)));
  402. else
  403. bts = Convert.FromBase64String(vs);
  404. //将指定的视图状态值转换为有限对象序列化 (LOS) 格式化的对象
  405. return new LosFormatter().Deserialize(new MemoryStream(bts));
  406. }
  407. #endregion
  408. #region 系统启动中
  409. static Boolean SystemStarted = false;
  410. /// <summary>
  411. /// 检查系统是否启动中,如果启动中,则显示进度条
  412. /// </summary>
  413. public static void CheckStarting()
  414. {
  415. if (HttpContext.Current == null) return;
  416. HttpRequest Request = HttpContext.Current.Request;
  417. HttpResponse Response = HttpContext.Current.Response;
  418. // 只处理GET,因为处理POST可能丢失提交的表单数据
  419. if (Request.HttpMethod != "GET") return;
  420. if (SystemStarted) return;
  421. SystemStarted = true;
  422. #region 输出脚本
  423. StringBuilder sb = new StringBuilder();
  424. sb.Append(@"<html><head>
  425. <script language=""javascript"" type=""text/javascript"">
  426. var t_id = setInterval(animate,20);
  427. var pos=0;var dir=2;var len=0;
  428. function animate(){
  429. var elem = document.getElementById('progress');
  430. if(elem != null) {
  431. if (pos==0) len += dir;
  432. if (len>32 || pos>79) pos += dir;
  433. if (pos>79) len -= dir;
  434. if (pos>79 && len==0) pos=0;
  435. elem.style.left = pos;
  436. elem.style.width = len;
  437. }
  438. }
  439. function stopAnimate(){
  440. clearInterval(t_id);
  441. var elem = document.getElementById('loader_container');
  442. elem.style.display='none';
  443. }
  444. </script>
  445. <style>
  446. #loader_container {text-align:center; position:absolute; top:40%; width:100%; left: 0;}
  447. #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;}
  448. #progress {height:5px; font-size:1px; width:1px; position:relative; top:1px; left:0px; background-color:#8894a8;}
  449. #loader_bg {background-color:#e4e7eb; position:relative; top:8px; left:8px; height:7px; width:113px; font-size:1px;}
  450. </style>
  451. </head><body>
  452. <div id=loader_container>
  453. <div id=loader>
  454. <div align=center>系统正在启动中 ...</div>
  455. <div id=loader_bg><div id=progress> </div></div>
  456. </div>
  457. </div>
  458. <div style=""position:absolute; left:1em; top:1em; width:320px; padding:.3em; background:#900; color:#fff; display:none;"">
  459. <strong>系统启动发生异常</strong>
  460. <div id=""start_fail""></div>
  461. </div>
  462. <script type=""text/javascript"" language=""javascript"">
  463. (function(w){
  464. var xhr;
  465. if(w.XMLHttpRequest && !w.ActiveXObject){
  466. xhr=new w.XMLHttpRequest();
  467. }else{
  468. try{
  469. xhr=new w.ActiveXObject('Microsoft.XMLHTTP');
  470. }catch(e){}
  471. }
  472. if(xhr){
  473. xhr.open('GET','?ajax=1');
  474. xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  475. xhr.onreadystatechange=function(){
  476. if(xhr.readyState===4){
  477. //只有返回http 200时才表示正常
  478. if(xhr.status===200){
  479. xhr=null;
  480. location.reload();
  481. }else{
  482. //否则输出http状态码和状态说明,以及返回的html
  483. stopAnimate();
  484. var ele=document.getElementById('start_fail');
  485. ele.innerHTML='HTTP '+xhr.status+' '+xhr.statusText+'<br/>'+xhr.responseText;
  486. var par=ele.parentNode;
  487. if(par){
  488. par.style.display='block';
  489. }
  490. }
  491. xhr=null;
  492. }
  493. };
  494. xhr.send();
  495. }else{
  496. // 不支持的浏览器将直接刷新 不再显示动画
  497. location.reload();
  498. }
  499. })(window);
  500. </script>
  501. </body></html>");
  502. //还可以选择使用<script src="?script=1" type="text/javascript"></script>的方式 只是对返回内容有要求
  503. //sb.AppendLine("function remove_loading() {");
  504. //sb.AppendLine(" this.clearInterval(t_id);");
  505. //sb.AppendLine("var targelem = document.getElementById('loader_container');");
  506. //sb.AppendLine("targelem.style.display='none';");
  507. //sb.AppendLine("targelem.style.visibility='hidden';");
  508. //sb.AppendLine("}");
  509. //sb.AppendLine("document.onload=function(){ location.reload(); }");
  510. //sb.AppendLine("document.onload=remove_loading;");
  511. Response.Write(sb.ToString());
  512. Response.Flush();
  513. Response.End();
  514. #endregion
  515. }
  516. #endregion
  517. }
  518. }