BlogEngine.Net架构与源代码分析系列part14:实现分析(下)——网站页面上值得参考的部分...

news/2024/5/20 9:43:58/文章来源:https://blog.csdn.net/weixin_30487701/article/details/95871936

     BlogEngine.Net的成功不仅在于它的架构设计,它的代码实现细节也都是很经典的,每个结构分割的很清晰很自然,希望大家多多品位一下。在这篇文章里我将给大家介绍一下BlogEngine.Net的Web实现上的几个亮点,包括Web.config,Ajax的运用等。

     Web.config中的几个结点说明

     让我们看一下appSettings结点中的各个选项的含义,以便您对整个BlogEngine.Net的认识更加清晰。
BlogEngine.FileExtension:在这里我们可以自定义Url请求的后缀名称,默认是.aspx。您可以定义自己喜欢的扩展名,例如.extguo,那么对于文章等生成的Url就成了类似http://HostName/CategoryName/PostTitle.extguo的形式。这个结点的使用在很多地方都可以见到,例如:

ContractedBlock.gifExpandedBlockStart.gifPost类中的RelativeLink
 1public string RelativeLink
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    get
 4ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 5        string slug = Utils.RemoveIllegalCharacters(Slug) + BlogSettings.Instance.FileExtension;
 6
 7        if (BlogSettings.Instance.TimeStampPostLinks)
 8            return Utils.RelativeWebRoot + "post/" + DateCreated.ToString("yyyy/MM/dd/", CultureInfo.InvariantCulture) + slug;
 9
10        return Utils.RelativeWebRoot + "post/" + slug;
11    }

12}

BlogSettings.Instance.FileExtension就是读取这个结点获得的扩展名。

BlogEngine.VirtualPath:主要是为一些文章等的链接而服务的。我们可以使用虚拟目录安装我们的BlogEngine.Net,那么我们只要设置一下这里就可以得到和直接在根目录下一样的效果。我们需要注意一下Utils关于Url处理的部分,其中:

ContractedBlock.gifExpandedBlockStart.gifUtils中的RelativeWebRoot
 1public static string RelativeWebRoot
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    get
 4ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 5        if (_RelativeWebRoot == null)
 6            _RelativeWebRoot = VirtualPathUtility.ToAbsolute(ConfigurationManager.AppSettings["BlogEngine.VirtualPath"]);
 7
 8        return _RelativeWebRoot;
 9    }

10}

就是获得相对Web目录。

BlogEngine.MobileDevices:它的值是一个正则表达式,主要是对移动设备做出判断,并给移动设备使用设置的主题。它在这里被使用:

ContractedBlock.gifExpandedBlockStart.gifUtils中的IsMobile判断
 1private static readonly Regex MOBILE_REGEX = new Regex(ConfigurationManager.AppSettings.Get("BlogEngine.MobileDevices"), RegexOptions.IgnoreCase | RegexOptions.Compiled);
 2
 3ExpandedBlockStart.gifContractedBlock.gif/**//// <summary>
 4/// Gets a value indicating whether the client is a mobile device.
 5/// </summary>
 6/// <value><c>true</c> if this instance is mobile; otherwise, <c>false</c>.</value>

 7public static bool IsMobile
 8ExpandedBlockStart.gifContractedBlock.gif{
 9    get
10ExpandedSubBlockStart.gifContractedSubBlock.gif    {
11        HttpContext context = HttpContext.Current;
12        if (context != null)
13ExpandedSubBlockStart.gifContractedSubBlock.gif        {
14            HttpRequest request = context.Request;
15            if (request.Browser.IsMobileDevice)
16                return true;
17
18            if (!string.IsNullOrEmpty(request.UserAgent) && MOBILE_REGEX.IsMatch(request.UserAgent))
19                return true;
20        }

21
22        return false;
23    }

24}

之后在BlogSetting的Theme中返回。

BlogEngine.AdminRole:管理员角色名,可以动态配置管理员角色,也就是说系统对是否是管理员的判断中的管理员名称实际上是从这儿获得的。比如有一天我们想把某个角色改为管理员,那么就直接修改这儿就行了,不过这儿需要的数据肯定也是角色管理中的一个角色名称。

StorageLocation:数据的存储位置,主要是给数据存储是XML格式时使用。在DataStore.cs文件中StorageLocation方法会涉及到。

BlogEngine.HardMinify:对于Javascript脚本指定强行压缩(去除一些不必要的字符)的文件名称。我们知道BlogEngine.Net中对于Javascript请求都是通过JavaScriptHandler进行的,JavaScriptHandler有一个HardMinify来判断是否已经指定强行压缩。JavaScriptHandler中会涉及到这部分的引用。注意对WebResource.axd的请求在BlogBasePage中替换成对于js.axd的请求,之后JavaScriptHandler的处理是使用RetrieveRemoteScript来输出脚本的。

     Ajax的运用

     BlogEngine.Net的很多部分使用原生的Ajax完成。例如评论的打分,widget的管理等部分。我们在讲述BlogBasePage时提到的AddLocalizationKeys实际上就是初始化页面脚本的一些变量,之后使用AddJavaScriptInclude(Utils.RelativeWebRoot + "blog.js")引入blog.js,如果是管理员(Widget可被管理)又使用AddJavaScriptInclude(Utils.RelativeWebRoot + "admin/widget.js")引入widget.js,使用AddStylesheetInclude(Utils.RelativeWebRoot + "admin/widget.css")引入widget样式,注意先后顺序,因为widget.js需要使用核心的blog.js。blog.js中这段代码就是Ajax调用的核心:

ContractedBlock.gifExpandedBlockStart.gifAjax核心
 1/// <summary>
 2/// Creates a client callback back to the requesting page
 3/// and calls the callback method with the response as parameter.
 4/// </summary>
 5function CreateCallback(url, callback)
 6ExpandedBlockStart.gifContractedBlock.gif{
 7  var http = GetHttpObject();
 8  http.open("GET", url, true);
 9  
10  http.onreadystatechange = function() 
11ExpandedSubBlockStart.gifContractedSubBlock.gif  {
12      if (http.readyState == 4
13ExpandedSubBlockStart.gifContractedSubBlock.gif      {
14        if (http.responseText.length > 0 && callback != null)
15        callback(http.responseText);
16      }

17  }
;
18  
19  http.send(null);
20}

21
22/// <summary>
23/// Creates a XmlHttpRequest object.
24/// </summary>
25function GetHttpObject() 
26ExpandedBlockStart.gifContractedBlock.gif{
27    if (typeof XMLHttpRequest != 'undefined')
28        return new XMLHttpRequest();
29    
30    try 
31ExpandedSubBlockStart.gifContractedSubBlock.gif    {
32        return new ActiveXObject("Msxml2.XMLHTTP");
33    }
 
34    catch (e) 
35ExpandedSubBlockStart.gifContractedSubBlock.gif    {
36        try 
37ExpandedSubBlockStart.gifContractedSubBlock.gif        {
38            return new ActiveXObject("Microsoft.XMLHTTP");
39        }
 
40ExpandedSubBlockStart.gifContractedSubBlock.gif        catch (e) {}
41    }

42    
43    return false;
44}

 

     在线评论预览与评论的提交

     结合blog.js与User controls\CommentView.ascx,我们看一下它的处理过程。CommentView可以显示文章的评论列表和提交新评论。当点击Preview时,会调用blog.js中的ToggleCommentMenu:

ContractedBlock.gifExpandedBlockStart.gif评论的预览与提交
 1// Shows the preview of the comment
 2function ToggleCommentMenu(element)
 3ExpandedBlockStart.gifContractedBlock.gif{
 4  element.className = 'selected';
 5  if (element.id == 'preview')
 6ExpandedSubBlockStart.gifContractedSubBlock.gif  {
 7    $('compose').className = '';    
 8    $('commentCompose').style.display = 'none';
 9    $('commentPreview').style.display = 'block';
10    $('commentPreview').innerHTML = '<img src="' + KEYwebRoot + 'pics/ajax-loader.gif" alt="Loading" />';
11    var argument = $('commentPreview').innerHTML;
12    AddComment(true);
13  }

14  else
15ExpandedSubBlockStart.gifContractedSubBlock.gif  {
16    $('preview').className = '';    
17    $('commentPreview').style.display = 'none';
18    $('commentCompose').style.display = 'block';    
19  }

20}

21
22function EndShowPreview(arg, context)
23ExpandedBlockStart.gifContractedBlock.gif{
24  $('commentPreview').innerHTML = arg;
25}

26
27function AddComment(preview)
28ExpandedBlockStart.gifContractedBlock.gif{
29  var isPreview = preview == true;
30  if (!isPreview)
31ExpandedSubBlockStart.gifContractedSubBlock.gif  {
32    $("btnSaveAjax").disabled = true;
33    $("ajaxLoader").style.display = "inline";
34    $("status").className = "";
35    $("status").innerHTML = KEYsavingTheComment;
36  }

37  
38  var author = nameBox.value;
39  var email = emailBox.value;
40  var website = websiteBox.value;
41  var country = countryDropDown ? countryDropDown.value : "";  
42  var content = contentBox.value;
43  var notify = $("cbNotify").checked;
44  var captcha = captchaField.value;
45   
46  var callback = isPreview ? EndShowPreview : AppendComment;
47  var argument = author + "-|-" + email + "-|-" + website + "-|-" + country + "-|-" + content + "-|-" + notify + "-|-" + isPreview + "-|-" + captcha;
48  
49  WebForm_DoCallback('ctl00$cphBody$CommentView1',argument, callback,'comment',null,false);
50  
51  if (!isPreview && typeof OnComment != "undefined")
52    OnComment(author, email, website, country, content);
53}

54

     请注意isPreview的引入与它的逻辑,这个Preview实际上也是需要回调到服务器端的程序的,之后生成预览的Render,当点击Save时isPreview为false,这时回调服务器端的代码时才真正的保存,然后浏览器回调客户端的AppendComment完成一些初始化工作。CommentView是一个UserControl并实现了ICallbackEventHandler接口,这个接口有两个方法GetCallbackResult和RaiseCallbackEvent,在RaiseCallbackEvent中我们可以看出,提交的评论参数使用"-|-"作为分隔符,经过一系列处理最后将这个新评论的呈现给了_Callback,_Callback由GetCallbackResult返回。浏览端使用WebForm_DoCallback('ctl00$cphBody$CommentView1',argument, callback,'comment',null,false);在这部分里我们只要实现ICallbackEventHandler接口就行了,实现的细节都已经有.Net提供了,感兴趣细节的朋友可以查一查Asp.Net的回调方面的资料。

     Widget排序的实现

     当我们用鼠标拖住一个Widget移动到某个位置再放开鼠标时,发现这个Widget在WidgetZone中的排序被永久存储了,甚至在你清空cookie时依然生效,BlogEngine.Net是在服务器端进行的存储,DataStore的be_WIDGET_ZONE中的Widget的顺序就是在页面上Widget的显示顺序。这实际上是通过间接调用WidgetEditor.aspx中的MoveWidgets方法实现的(前文提及过)。那么在浏览器端是如何处理这些排序问题的呢?

     在widget.js中的大部分代码都是用来处理拖放排序的,initdragableElements主要完成使某个Widget可以被拖动的初始化工作,widget.js的最后一句代码addLoadEvent(initdragableElements)使其在页面加载时执行。注意initdragableElements中:

ContractedBlock.gifExpandedBlockStart.gif拖动事件的Hookup
1document.body.onmousemove = moveDragableElement;
2document.body.onmouseup = stop_dragDropElement;
3document.body.onselectstart = cancelSelectionEvent;
4document.body.ondragstart = cancelEvent;
5window.onresize = repositionDragObjectArray;

当鼠标onmouseup时执行stop_dragDropElement,在stop_dragDropElement中通过调用saveData,saveData使用上文提到的CreateCallback完成服务器端的回调,其中saveString就是已排序的字符串,主要用于发送给服务器端程序处理。

     总结

     实际上在BlogEngine.Net的Web站点中还有很多比较有用的东西值得我们去研究,例如FilterByApml的实现,对文章的评分,邮件的发送等,这里就不做更多的讨论。关于在线评论预览我个人觉得没有必要去回调服务器,完全可以由客户端搞定,不知道大家是怎么想的。那个Widget的排序一直都深深的吸引着我,这种处理我见得很少,所以拿出来分享。

     在本系列的最后一篇文章中我会就BlogEngine.Net的优秀部分和不太推荐的部分做一个总结,并谈一下我对它的感受,希望大家继续关注。

     坚持写完,坚持看完。

     上一篇:BlogEngine.Net架构与源代码分析系列part13:实现分析(上)——HttpHandlers与HttpModules

     下一篇:BlogEngine.Net架构与源代码分析系列part15:总结篇

 

     返回到目录

转载于:https://www.cnblogs.com/Thriving-Country/archive/2008/11/14/1332974.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_810312.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【第一期】如何打造属于自己的网站编辑器——CKEditor与UEditor之争

首先说明一下由于经常写项目最近比较忙&#xff0c;所以一直没时间整理文章&#xff0c;现在把近阶段的一些心得分享出来&#xff0c;这是第一期&#xff0c;接下来我会跟大家讲讲ASP.NET单层&#xff0c;三层&#xff0c;以及多层开发企业建站和具体要求和操作&#xff0c;希望…

网站上显示农历及阳历节日

把阳历日期转换为农历用到的函数为ChinaDate.ConvertToNongLi(DateTime.Now); 得到节日的函数为 ChinaDate.GetFestival(DateTime.Now); 代码&#xff1a; using System.Globalization; using System.Collections; using System;namespace NetWeb2011.Common {public static cl…

AWWWB 网站克隆器 v1.0 发布

软件名称&#xff1a;AWWWB.COM网站克隆器1.0 开发商&#xff08;主页&#xff09;&#xff1a;www.awwwb.com 联系人&#xff1a;awwwb.comqq.com 软件性质&#xff1a;免费软件/开源软件 软件描述&#xff1a; AWWWB.COM网站克隆器&#xff1a;输入被克隆网站的首页网址&…

一个Java语言所写的shop网站框架明细

核心框架Spring Framework &#xff1a;作为一个优秀的开源框架&#xff0c;是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构&#xff0c;分层架构允许您选择使用哪一个组件&#xff0c;同时为 J2EE 应用程序开发提供集成的框架。 模板引擎FreeM…

iframe懒加载_wordpress网站视频和图片懒加载插件的对比与使用 a3 Lazy Load

都说wordpress网站速度慢&#xff0c;三人成虎&#xff0c;养虎为患&#xff0c;今天就推荐个使wordpress网站提速度的插件。特别是图片或者视频较多的站&#xff0c;用个懒加载插件将大大减少一时的http(s)请求、减少服务器端压力&#xff0c;使服务器按需加载。对于用户体验&…

php教育网站设计案例_UI设计素材模板|设计良好的教育网站:3个快捷技巧

拥有一个高质量的学校网站比以往任何时候都更重要。优秀的UI设计素材模板&#xff0c;帮助设计师和管理人员建立最好的教育网站。从成功的设计中寻找灵感&#xff01;3个快捷技巧1. 使用教育专用的网站构建器首先&#xff0c;用专门教育内容管理系统(CMS)来制作学校网站是个好主…

服务器内部移动文件速度慢,网站打开速度慢的原因分析已经解决排查方案(实用大全)...

72018/7网站打开速度慢的原因分析已经解决排查方案(实用大全)飞鸟哥上百个案例&#xff0c;3天整理,实证案例&#xff0c;全面&#xff0c;实用&#xff01;假如你是网站提供者&#xff0c;或者网站运营者看下文本给你专业全面的经验。飞鸟哥&#xff0c;根据10年经验&#xff…

秒杀全网!研发、运营必备实用工具网站

目录 1、搜索引擎 2、PPT 3、图片操作 4、文件共享 5、招聘求职 6、程序员面试题库 7、办公、开发软件 8、高清图片、视频素材网站 9、项目开源 10、算法 11、在线工具宝典大全 12、音乐 13、神辅助工具 14、语音处理 15、大数据 16、电子书 程序员开发需要具…

【织梦插件】xenu软件-网站url和死链提取工具免费下载

软件名称xenu软件作用网站网址提取工具适宜人群SEO网址http://www.jingdouwang.cn/zygx/wzcj/278.html 软件简介&#xff1a; Xenu Link Sleuth 可能是你所见功能最强大的网站死链接查询的软件了。使用方法简单&#xff0c;仅需要输入网站URL就可以完成死链查询。用户可直接查看…

IIS部署,发布网站

因项目需要&#xff0c;正在学习如何部署IIS服务&#xff0c;发布网站&#xff0c;将遇到的问题记录下。 一、IIS部署 1.打开控制面板&#xff0c;选择 ‘程序’ 2.程序和功能下&#xff0c;选择打开或关闭Windows功能 3.等待加载&#xff0c;选择Internet信息服务&#xff0…

网站业务架构演变过程

有一天&#xff0c;我突发奇想创建了一个站点&#xff0c;基于LNMP架构&#xff0c;起初只有我自己访问&#xff0c;后来因为我点儿正&#xff0c;访问量越来越大&#xff0c;所以最终导致下面的架构演变。1. 单台机器因为只是一个小站&#xff0c;访问量一天也没有多少uv&…

做网站服务器e3,用e3做游戏服务器

用e3做游戏服务器 内容精选换一换下面以CentOS 6.9 (x86_64)操作系统为例&#xff0c;举例介绍裸金属服务器增强高速网卡的配置方法。RedHat系列、Oracle Linux系列、Euler系列及CentOS系列操作系统的配置方法类似。以“root”用户&#xff0c;使用密钥或密码登录裸金属服务器。…

Python+Flask+MysqL的web建设技术开发一个网站

一、摘要 flask是一个很精简&#xff0c;灵活的框架&#xff0c;对于web的开发非常的好&#xff0c;具有jinja2强大的模板引擎的支持。flask框架的一个扩展就是sqlalchemy, sqlalcheny是flask的一个扩展。sqlalcheny是一个强大的关系型数据库框架&#xff0c;它是一个框架&…

MCSE笔记 第四章 IIS网站架设

以前大学时候上过网络操作系统这门课程&#xff0c;当时用的是Windows 2003弄的IIS&#xff0c;工作中接触过2008、2003系统搭建的IIS&#xff0c;都不太熟悉&#xff0c;最近看的戴有炜老师的2012网络管理与架站&#xff0c;整理一下IIS章节的笔记。大致内容如上图所示:1.安装…

网站规划通识:原型图绘制的一些注意事项

本文来自网易云社区作者&#xff1a;林玮园 雷火游戏部 网站组基本概念&#xff1a; 一、什么叫原型图&#xff1f;用线条、图形描绘出产品/专题的框架&#xff0c;即为原型&#xff0c;也可称线框图。原型图的输出可根据质量&#xff0c;大致分为低保真、中保真、高保真原型图…

客户网站被挂马的分析

打开网站,查看 源代码 ,查找<iframe 标签 就会找到在这段框架:<iframe src"http://www.fengyajade.com/jiaozhu.htm" name"zhu" width"0" height"0" frameborder"0">这就是 打开网站为什么,杀毒软件提示有木马的原…

实现域名访问网站—nginx反向代理

今天在跟项目的时候&#xff0c;上午被耍了三个多小时&#xff0c;最后在我准备好材料准备他人求助的时候&#xff0c;在收集材料的时候&#xff0c;居然访问通了&#xff0c; 别问我为什么&#xff0c;我也不知道 &#xff0c;哈哈哈哈&#xff08;苦逼脸...&#xff09; 分享…

如何构建安全的电子商务网站

摘 要 本文总结了电子商务对安全性的要求&#xff0c;介绍了构成一个安全的电子商务系统的框架。介绍了安全通信协议SSL和SET&#xff0c;分析了其优缺点。最后&#xff0c;给出一个例子来指导如何建立一个基于SSL的安全网站。关键词 电子商务 PKI SSL TLS一、电子商务安…

企业网站制作之PageAdmin自助建站系统

企业网站现在已经是网络营销的标配&#xff0c;目前制作一个企业的网站&#xff0c;要么找网站制作公司&#xff0c;要么下载网站管理系统自己搭建&#xff0c;找网站公司的优点是&#xff1a;省心;缺点&#xff1a;后期维护和扩展都需要借助网站公司实现&#xff0c;完全依靠网…

[JavaScript]给自己的网站添加简单文本日志

1.用于记录日志的文件 log.asp&#xff0c;另外需要建立一个用于保存日志文件的文件夹logs。log.asp文件的代码如下&#xff1a; <script language"javascript"runat"server">varfso newActiveXObject("Scripting.FileSystemObject");vard…