系统日志和异常的处理②
上一讲我们做了日志与异常的结果显示列表,这一节我们讲要把他应用系统中来。
首先我们在App.Common类库中创建一个通用类ResultHelper,这个类里面写了,获取一个GUID,获取当前时间,处理字符串等操作,虽然我们目前要用到的一个就是获取GUID但是以后我们可能还要用到别的,所以我都把他放进入了
然后在App.Admin创建一个核心文件夹,Core,放入LogHandler这个类是主要是写入日志,避免在每次都要实例化这个类,我把他封装起来,大家一看就知道。
然后修改Controller的Create方法,代码如下一一给出。
同时App.Common要引用程序集System.Web
运行添加一条记录,然后打开我们的日志模块,OK,日志记录完成了,有点简单。
接下来是异常,上一讲说到,异常我们放在BLL中处理,然后我们把错误或者异常信息返回到Controller中被日志记录,当然异常他是在BLL层被记录的。
我们需要一个异常的集合类,来记录BLL层和DAL层,有时候DAL也要处理异常,所以我们也要用到ref 引用传递,貌似ref我们很喜欢,呵呵
见代码,在App.Common创建一个异常集合类
我们也要创建一个封装好的异常写入,类似与Log的LogHandler封装但我们放在BLL中,因为我们以后的其他项目的BLL要引用,这一步要考虑到。
在BLL中创建文件夹Core,写入以下类,BLL引用程序集System.Web里面用到了http的一些方法
此异常当处理也异常时候,将在网站根目录下写入一个txt文件。
创建一个全局变量
ValidationErrors errors = new ValidationErrors();
我们要用引用传递,所以要修改IBLL和BLL的Create方法,如下
ISysSampleBLL : bool Create(ref ValidationErrors errors, SysSampleModel model);
SysSampleBLL :
/// <summary> /// 创建一个实体 /// </summary> /// <param name="errors">持久的错误信息</param> /// <param name="model">模型</param> /// <returns>是否成功</returns> /// <summary> /// 创建一个实体 /// </summary> /// <param name="errors">持久的错误信息</param> /// <param name="model">模型</param> /// <returns>是否成功</returns> public bool Create(ref ValidationErrors errors, SysSampleModel model) { try { SysSample entity = Rep.GetById(model.Id); if (entity != null) { errors.Add("主键重复"); return false; } entity = new SysSample(); entity.Id = model.Id; entity.Name = model.Name; entity.Age = model.Age; entity.Bir = model.Bir; entity.Photo = model.Photo; entity.Note = model.Note; entity.CreateTime = model.CreateTime; if (Rep.Create(entity) == 1) { return true; } else { errors.Add("插入失败"); return false; } } catch (Exception ex) { errors.Add(ex.Message); ExceptionHander.WriteException(ex); return false; } }
修改Controller
[HttpPost] public JsonResult Create(SysSampleModel model) { if (m_BLL.Create(ref errors, model)) { LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name, "成功", "创建", "样例程序"); return Json(1, JsonRequestBehavior.AllowGet); } else { string ErrorCol = errors.Error; LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name + "," + ErrorCol, "失败", "创建", "样例程序"); return Json(0, JsonRequestBehavior.AllowGet); } }
注意:ExceptionHander.WriteException(ex);这里是写入异常信息
OK,你现在可以创建一条新的记录和插入一个ID大于50个字符的记录,让他记录日志和异常了。
显然我们的失败错误提示已经不符合国情了。我们返回的json格式是0和1我们要返回多个值了,比如1和成功创建,0和失败了啊,这样的2个值怎么办?
controller能把datagrid传过来的东西用类来接受,那么反过来想,js也能把controller发出去的值分解,创建一个序列化的类
在App.Common类库中创建JsonHandler帮助类,里面有2个重载,一个是返回3个值一个是2个值的。
所以当我们要返回订单的数量和总价格的时候,我们将用到类似的手段
再次修改Controller的Create
[HttpPost] public JsonResult Create(SysSampleModel model) { if (m_BLL.Create(ref errors, model)) { LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name, "成功", "创建", "样例程序"); return Json(JsonHandler.CreateMessage(1, "插入成功"), JsonRequestBehavior.AllowGet); } else { string ErrorCol = errors.Error; LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name + "," + ErrorCol, "失败", "创建", "样例程序"); return Json(JsonHandler.CreateMessage(0, "插入失败" + ErrorCol), JsonRequestBehavior.AllowGet); } }
修改SysSample的Create的JS部分
<script type="text/javascript"> $(function () { $("#btnSave").click(function () { if ($("#CreateForm").valid()) { $.ajax({ url: "/SysSample/Create", type: "Post", data: $("#CreateForm").serialize(), dataType: "json", success: function (data) { if (data.type == 1) { window.parent.frameReturnByMes(data.message); window.parent.frameReturnByReload(true); window.parent.frameReturnByClose() } else { window.parent.frameReturnByMes(data.message); } } }); } return false; }); }); </script>
由于时间关系,这一讲就先到这里吧!这一讲其实比较仓促。不懂的留言
你需要继续做的就是在删除,编辑等操作也加入这些的。这点留给大家自己表现吧....
下一讲是全局异常的捕获。
bmrxntfj
看过《大湿教我写.net通用权限框架(1)之菜单导航篇》之后发生的事
引言
本来是想继续UML学习系列的,今天换换内容,一直弄那个也挺无聊的,在博客园看到这位牛人怎么扣界面的,觉得很新奇,今天也尝试了。确实很牛逼。这里也将学习结果分享一下。十分感谢@微软高级php工程师,膜拜啊。原文地址:大湿教我写.net通用权限框架(1)之菜单导航篇
他的文章下面有三个链接,这里就做个简单的,怎么扣登录界面?
患者:登录界面
手术台:火狐浏览器
主刀人:LZ
操刀过程
解剖
1)首先根据他给的链接进入登录界面http://223.86.105.239:803/Frame/Login.htm
这界面还第一次见到,不让我右键,不让我F12(IE浏览器F12有效,其他浏览器F12没反应......),那只能
2)查看源代码
取内脏
样式怎么扣下来?单击进去,比如desktop.css这个样式文件。
然后是jquery,这个可以去下载,或者进去复制,然后在项目中,新建一个同样名称的js文件。
关于FunctionJs这个js文件,一看就是自定义的,点进去,复制,新建一个同名的js文件。
必须指出,如果你不想后期很麻烦,建议你根据它的路径名来新建,根据上面的可以得出 大概的结构如下:
样式和jquery有了,下面就是图片了,这东西还真麻烦,一个登录界面涉及到的图片还不少,首先找html源码中有没有图片的url:
就喜欢界面上的东西,真的可以直接单击,进去了,然后另存为,这个图片就有了。
然后,查看样式中有没有图片地址:
最头疼的就是这个,这样的还真不少.......
没办法去拼吧,该怎么拼?程序员的习惯,喜欢把图片放在一个文件夹中,通过页面上的那个地址大概知道:/Themes/Images/这个目录下是存图片的。
那么加上域名试试:http://223.86.105.239:803/Themes/images/Login/bj.jpg
其他的依葫芦画瓢慢慢扣吧,不过中间可能会遇到返回404的,检查地址是否写错,如果没写错,看一下对页面布局有影响没,没影响的话也可以不要那张。
尝试了,没办法获取这张图片.....
总结
大神就是大神,突然想到一句广告词:“自从有了学习机,mama再也不用担心我的学习”,期待他的后续文章。
手术结束,缝针还原它
看别人写的不错,自己实践一下,也不是新东西,只是LZ经常关注博客园,喜欢将里面的代码,操作,亲自做一遍,强迫症严重,不操刀,心里不舒服。
看到的是别人的,操刀实践了,才有可能是自己的......虽然不是专业前端,但是基本的抠图还是得学一点的.....
再次感谢:微软高级php工程师
实现自己的js框架
两年前写的,现在发出来,也当是一个记录。
我知道贴代码有些人会反对,觉得应该用文字讲细致,但是我觉得用文字我没发用简单的文字来表达,看代码反而更直接,这个是见仁见智的。
很早之前一直用extjs,这个确实非常强大,但是在IE下一直都有一个性能的问题,搞得要让客户换chrome,firefox浏览器才行。
之所以要写自己js框架,原因是觉得自己实现也简单,维护也方便,一些管理应用的项目可以用,网站这些我还是推荐直接使用jquery,毕竟更加简单直接没有那么多可给你重复应用的地方。
可能你要问为什么不用jquery插件,一样可以。但是这些插件代码质量不能保证,风格也是奇形怪状,出了问题还要去看代码,改了之后又跟原作者的有出入,以后同步更加麻烦。
不用jquery插件,但是jquery却是个好东西,解决了浏览器兼容的大问题,所以我这个就是基于jquery来实现的,因为一直喜欢extjs的代码风格,所以如果你使用过extjs的话,使用起来会轻车熟路。
js的继承是原型继承的方式,最开始的时候我确实也用原型的方式来实现,但是后面我发现有些问题,而且理解起来不是太清晰,所以我采用一种简单清晰的方法,写起来是继承但是实际上它只是一个对象。
它同样有着抽象方法,有父类,有重载,有重写等等。
先看一下大概结构如下图:
现在说下几个重要的地方
首先就是如何定义一个类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
define: function (className, defaultConfig) { if (!wyl.isString(className) || className.isEmpty()) { throw new Error( "[wyl.define] Invalid class name '" + className + "' specified, must be a non-empty string" ); } var namespace_arr = className.split( '.' ); var namespace = window; var class_Name = namespace_arr.last(); wyl.each(namespace_arr, function (ns) { if (ns == class_Name) { return ; } if (!namespace[ns]) { namespace[ns] = {}; } namespace = namespace[ns]; }); if (namespace[class_Name]) { throw new Error( '重复定义了' + className); } defaultConfig.className = className; for ( var p in defaultConfig) { if (wyl.isFunction(defaultConfig[p])) { defaultConfig[p].fnName = p; } } namespace[class_Name] = defaultConfig; } |
接着就是如何创建一个类的实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
getDefineConfig: function (namespaces, i, context) { if (context == null ) { return null ; } if (namespaces.length == i) { return context; } var ns = namespaces[i]; return wyl.getDefineConfig(namespaces, i + 1, context[ns]); } create: function (className, config) { if (!wyl.isString(className) || className.isEmpty()) { throw new Error( "[wyl.create] Invalid class name '" + nsclassName + "' specified, must be a non-empty string" ); } var namespaces = className.split( '.' ); var defineConfig = wyl.getDefineConfig(namespaces, 0, window); if (!defineConfig) { throw '{0}类型未定义。' .format(className); } config = config || {}; if (!config.id) { config.id = wyl.newId(); } var instance = {}; wyl.apply(instance, config, defineConfig); //继承的关键代码如下 if (instance.extend) { var base = wyl.create(instance.extend); for ( var p in base) { if (instance.hasOwnProperty(p)) { //把父类的方法重新命名赋值到这个实例上 if (wyl.isFunction(instance[p]) && wyl.isFunction(base[p])) { var baseFnName = instance.extend + '_' + p; instance[p][ 'baseFnName' ] = instance.extend + '_' + p; instance[baseFnName] = base[p]; } } else { instance[p] = base[p]; } } } instance.initConfig = config; if ( typeof (instance.init) == 'function' ) { instance.init.apply(instance); } if (wyl.isFunction(instance.initComponent)) { instance.initComponent.apply(instance); } wyl.each(instance.abstractMethods, function (methodName) { this [methodName] = function () { throw this .className + ' has not implement ' + methodName; } }, this ); this .intanceMgr[instance.id] = instance; return instance; } |
对于所有的类型我定义了一个基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
wyl.define( 'wyl.object' , { initConfig: null , abstractMethods: [], //ext4.0中调用父类的方法就是这个 callParent: function () { var me = this ; //调用的时候根据之前create里面加入的隐藏信息baseFnName来找到父类的方法并调用它 var fnname = me.callParent.caller[ 'baseFnName' ]; var fn = me[fnname]; if (wyl.isFunction(fn)) { fn.call(me); } }, addEvents: function () { var me = this ; if (!wyl.eventMgr[me.id]) { wyl.eventMgr[me.id] = {}; } var myEventMgr = wyl.eventMgr[me.id]; wyl.each(arguments, function (eventName) { if (!myEventMgr[eventName]) { myEventMgr[eventName] = []; } }); }, fireEvent: function (eventName, prams) { var me = this ; var myEventMgr = wyl.eventMgr[me.id]; var listeners = myEventMgr[eventName]; if (wyl.isArray(listeners)) { wyl.each(listeners, function (listener) { var scope = listener.scope ? listener.scope : this ; if (listener.callback && typeof (listener.callback) == 'function' ) { listener.callback.call(scope, prams); } }); } }, on: function (eventName, options) { var me = this ; if (!wyl.eventMgr[me.id]) { wyl.eventMgr[me.id] = {}; } var myEventMgr = wyl.eventMgr[me.id]; if (!myEventMgr[eventName]) { myEventMgr[eventName] = []; } var removeIndex = null ; wyl.each(myEventMgr[eventName], function (item, i) { var b = options.callback == item.callback; if (b) { removeIndex = i; } return !b; }); if (removeIndex && removeIndex > -1) { myEventMgr[eventName].removeAt(removeIndex); } myEventMgr[eventName].push(options); }, destroy: function () { delete wyl.eventMgr[ this .id]; delete wyl.intanceMgr[ this .id]; }, init: function () { wyl.apply( this , this .initConfig); } }); |
界面的控件,我也定义了一个基类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
wyl.define( 'wyl.Component' , { extend: 'wyl.object' , containerSelector: null , container: null , abstractMethods: [ 'render' ], getContainer: function () { if ( this .container === null ) { this .container = $( this .containerSelector).first(); if ( this .container == null ) { throw '控件必须要设置containerSelector或不存在.' ; } } return this .container; }, setContainer: function (selector) { if ( typeof (selector) != 'string' ) { throw '设置container必须是string类型.' ; } this .containerSelector = selector; }, getWidth: function () { return this .getContainer().width() - 2; }, getHeight: function () { return this .getContainer().height() - 2; } }); |
大概的思路就是容器会负责分配给下面子控件的容器setContainer,子控件得到自己的容器getContainer,一个控件不需要关系其他控件,只需要控制好自己内部的控件元素就行了。
里面定义了一个抽象方法render,每个控件都必须实现这个方法。容器render的时候,同时如果自己内部有子控件,也render自己内部的子控件。