关于html+ashx开发中几个问题的解决方法


Posted in Javascript onJuly 18, 2011

问题1:用委托字典代替switch...case。

这个问题是在处理请求时发现的,大家肯定也不愿意在自己的项目中建许多的handler来处理那么多的请求,于是就想到在一个handler里处理多个请求,ajax请求中都加一个action的参数,在handler里根据这个action做相应的处理或返回相应的数据,这里肯定没有人用if...else来判断action,大多数人都会想到用switch...case,一开始我也是用的switch,但渐渐地发现,每个case不像一个代码块,不能为其中的变量提供一个独立的作用域!用龙珠中孙悟空的话“真是伤脑筋”。

在网上搜了一下,也有不少人遇到这个问题。有个解决方法是把每个处理单独成handler里一个方法,这样清楚明了,但在ProcessRequest方法中要用反射调用对应的方法!自己对这个解决办法不太满意,于是想到了委托,想到了字典,把反射调用方法变成在字典里索引委托。

首先在handler里声明一个私有的静态委托字典:

static Dictionary<string, Func<string>> hs;

然后用handler(一般处理程序的类)里静态构造函数初始化hs,更重要的是要在静态构造函数里添加处理方法:

static Handler() 

{ 


hs = new Dictionary<string, Func<string>>(); 


hs.Add("add", delegate() 


{ 



int id = int.Parse(req("id")); 



string title = req("title"); 



return "add"; 


}); 


hs.Add("update", delegate() 


{ 



int id = int.Parse(req("id")); 



string title = req("title"); 



return "update"; 


}); 

}

最后就是在ProcessRequest方法里调用了:

context.Response.ContentType = "text/plain"; 

HttpRequest req = context.Request; 

string action = req["action"].ToLower(); 

string result = hs[action](); 

context.Response.Write(result);

这样便避免了switch...case的变量作用域问题和反射的效率问题。关于上面用到的req()方法,我的想法是把公共的东西用静态方法提供,如:

static string req(string key) 

{ 


return HttpContext.Current.Request[key]; 

} 

static string jss(object obj) 

{ 


JavaScriptSerializer JSS = new JavaScriptSerializer(); 


return JSS.Serialize(obj); 

}

问题2:权限问题。

你肯定不愿自己的数据在用户没有登陆或登陆过期后还可以继续访问。这里假设登陆的用户用Session["user"]来存储,当然在handler里判断一下Session["user"]是很简单的事情,但问题是你如何让Session["user"]为null时的用户跳转到指定页(这里假设是登陆页login.html)。哈哈,这时你会不会想到用context.Response.Redirect ("login.html")这样一句话来解决呢!我的第一反映是这样的,但分析一下,ajax是请求数据的,这样做是让ajax去请求login.html这个页面,得到的结果应该是login.html的源代码才对,分析是这样分析的,可还是不死心,还是测试了一下,结果正如分析的那样,login.html的源代码做为ajax请求结果返回了!

其实,大家心理明白,有一个很简单的方法,就是在Session["user"]为null时返回一个特定值,这里假设"unlogin",然后在每次ajax请求完成后判断返回值是不是"unlogin"。

这方法很简单,也很可靠,但很笨,很麻烦,可行性不高。于是我又想到了jquery.ajaxSuccess(),想用它来做统一处理,在我想到它的时候我就有点儿担心,jquery会不会是先调用具体请求的回调函数然后再调用这全局的回调函数呢?我带着这个疑问做了测试,结果也如预料那样先执行具体请求的回调再执行全局回调!没法办,只好查jquery的源码了~。在没压缩的jquery-1.4.2.js里找到了success()这方法,果然如此,改顺序后如下:

function success() { 


if ( s.global ) { 



trigger( "ajaxSuccess", [xhr, s] ); 


} 


// If a local callback was specified, fire it and pass it the data 


if ( s.success && xhr.responseText!="unlogin" ) { 



s.success.call( callbackContext, data, status, xhr ); 


} 

}

执行顺序是改好了,可跳转的代码写哪呢?每个页面写一次?不不,这不是我们写程序的风格,思来想去,写到jquery文件里(最下面)是一个可行的方法:

$(document).ajaxSuccess(function(event,xhr,settings){ 
if(xhr.responseText=="unlogin"){ 
window.top.location.href="/login.html"; 
} 
})

很显示,不是每个页面的ajax请求都要求用户登陆,比如login.html页,所以判断时要排除不用登陆的页面:

if (HttpContext.Current.Request.UrlReferrer.ToString().ToLower().IndexOf("login.html") < 0) 

{ 


if (HttpContext.Current.Session["user"] == null) 


{ 



HttpContext.Current.Response.Write("unlogin"); 



HttpContext.Current.Response.End(); 


} 

}

问题3:数据模板。

真是什么东西需要,什么都东西就应运而生!在写这个随笔之前正好在园里看到了个jquery.tmpl的文章!tmpl的产生也正是解决这个问题的!我很自知这个方法没tmpl强大,但tmpl有一个问题没有解决,其实模板有两个主要的问题,1是如果模板存储在js里不好编辑,2是要把模板存储在哪里才方便设计时的视图呢!tmpl把模板存储在<script type="text/x-jquery-tmpl"></script>标签中,应该说是解决了第一个问题,但我感觉第2个问题也是很重要的!想来想去,只能把模板直接存储在数据的容器标记里:

<ul id="ulList"> 
<li><a href="somepage.html?id={ID}">{Title}</a><br /> 
{Content}</li> 
</ul>

把模板直接写在目标容器里,就像一条数据一样,美工调样式不是问题,程序加方法不是问题,这方法我看行!但js肯定不会直接操作这个模板吧,现在要做的就是把这个模板变成真的模板:

$(function() { 


var ulList = $("#ulList"); 


ulList.data("tpl",ulList.html()).empty(); 

}

把模板存储到容器的data里应该是再适当不过了,而且这个操作在页面加载完马上就做!然后把容器清空,让位给后来加载过来的真实数据。后台提供json数据,这个很简单:

public class News 
{ 
public int ID { get; set; } 
public string Title { get; set; } 
public string Content { get; set; } 
} 
//handler里用了上面第一个问题的解决方法 
hs.Add("getNews", delegate() 

{ 


List<News> list = new List<News>() 


{ 



new News(){ ID=1,Title="title1",Content="Content1"}, 



new News(){ ID=2,Title="title2",Content="Content2"}, 



new News(){ ID=3,Title="title3",Content="Content3"}, 


}; 


return jss(list); 

});

前台取数据没什么好说的,这个很基本:

$.get("Handler.ashx?n=" + Math.random(), { action: "getNews" }, function(data) { 
var list = $.parseJSON(data); 
var ul = $("#ulList"); 
var html = ""; 
for (var i = 0; i < list.length; i++) { 
html += ul.data("tpl").format(list[i]); 
} 
ul.html(html); 
})

在填充数据的时候用了string.format这个方法,它在我js中的string.format 随笔里有记录,呵呵,这个我也没有想到,写format的时候让它支持json对象只是为了阅读方便,然而用到这如此合适!到这的时候我已兴奋不已了,测试结果如下:

关于html+ashx开发中几个问题的解决方法

但当我加了事件后,我发现还不够好。如果在模板li里加上onclick="show({ID},'{Title}')",IE里刚打开页面的时候就会有js错误,这是为什么呢?问题在这个ID参数上,因为{ID}被看作json对象了,而它却是一个格式不对的json! 提示js错误也正常,'{Title}'没有错误是原因这里看作字符串参数了。这个js错误虽然不影响程序,但没有人不喜欢自己写的代码是没有js错误的! 解决方法很简单,像Title参数一样加引号就可以了,如果show方法里真的要数字类型,只好在那里转换一下喽!不过你肯定会发现,很多时候是不用转换的,甚至你还希望它就是个字符串类型呢!

从没有这么认真的写过随笔,三个星期就休息了这一下午,没陪女朋友,没睡大觉,没找朋友喝酒,却老老实实地把它完成了!

Javascript 相关文章推荐
jquery 插件 任意位置浮动固定层
Dec 25 Javascript
下拉菜单点击实现连接跳转功能的js代码
May 19 Javascript
解析prototype,JQuery中跳出each循环的方法
Dec 12 Javascript
JQuery.get提交页面不跳转的解决方法
Jan 13 Javascript
JavaScript中的boolean布尔值使用学习及相关技巧讲解
May 26 Javascript
js 实现数值的千分位及保存小数方法(推荐)
Aug 01 Javascript
老生常谈ES6中的类
Jul 31 Javascript
基于canvas粒子系统的构建详解
Aug 31 Javascript
利用javascript如何随机生成一定位数的密码
Sep 22 Javascript
vue-router中scrollBehavior的巧妙用法
Jul 09 Javascript
jquery 回调操作实例分析【回调成功与回调失败的情况】
Sep 27 jQuery
为什么Vue3.0使用Proxy实现数据监听(defineProperty表示不背这个锅)
Oct 14 Javascript
TreeView 用法(有代码)(asp.net)
Jul 15 #Javascript
基于jquery实现的鼠标滑过按钮改变背景图片
Jul 15 #Javascript
jquery 结合C#后台的数组对文章的关键字自动添加链接的代码
Jul 15 #Javascript
js实现addClass,removeClass,hasClass的函数代码
Jul 13 #Javascript
js下将字符串当函数执行的方法
Jul 13 #Javascript
JS高级笔记
Jul 13 #Javascript
JS继承 笔记
Jul 13 #Javascript
You might like
用PHP和Shell写Hadoop的MapReduce程序
2014/04/15 PHP
php实现留言板功能
2017/03/05 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
PHP实现的抓取小说网站内容功能示例
2019/06/27 PHP
JavaScript 异步调用框架 (Part 1 - 问题 &amp; 场景)
2009/08/03 Javascript
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
2009/11/12 Javascript
jquery 经典动画菜单效果代码
2010/01/26 Javascript
基于jQuery的倒计时实现代码
2012/05/30 Javascript
关于JavaScript的面向对象和继承有利新手学习
2013/01/11 Javascript
nullJavascript中创建对象的五种方法实例
2013/05/07 Javascript
浅析javascript中函数声明和函数表达式的区别
2015/02/15 Javascript
JavaScript判断是否为数组的3种方法及效率比较
2015/04/01 Javascript
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
2016/07/26 NodeJs
jQuery实现的简单排序功能示例【冒泡排序】
2017/01/13 Javascript
nodejs入门教程四:URL相关模块用法分析
2017/04/24 NodeJs
Node.js操作redis实现添加查询功能
2017/05/25 Javascript
axios实现简单文件上传功能
2019/09/25 Javascript
用Python编写简单的定时器的方法
2015/05/02 Python
详解Django中的权限和组以及消息
2015/07/23 Python
Python简单连接MongoDB数据库的方法
2016/03/15 Python
Python反射和内置方法重写操作详解
2018/08/27 Python
详解python中init方法和随机数方法
2019/03/13 Python
python实现对象列表根据某个属性排序的方法详解
2019/06/11 Python
python代码如何实现余弦相似性计算
2020/02/09 Python
如何在VSCode下使用Jupyter的教程详解
2020/07/13 Python
scrapy处理python爬虫调度详解
2020/11/23 Python
真正了解CSS3背景下的@font face规则
2017/05/04 HTML / CSS
美国在线珠宝商店:SZUL
2017/02/11 全球购物
工程预算与管理应届生求职信
2013/10/06 职场文书
文秘专业应届生求职信范文
2013/11/14 职场文书
法定代表人证明书
2014/11/28 职场文书
复试通知单模板
2015/04/24 职场文书
2015小学教师年度工作总结
2015/05/12 职场文书
2015年度优秀员工获奖感言
2015/07/31 职场文书
《我和小伙伴》教学反思
2016/02/20 职场文书
Python爬虫中urllib3与urllib的区别是什么
2021/07/21 Python