关于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 相关文章推荐
用js实现下载远程文件并保存在本地的脚本
May 06 Javascript
javascript实现的距离现在多长时间后的一个格式化的日期
Oct 29 Javascript
jQuery队列控制方法详解queue()/dequeue()/clearQueue()
Dec 02 Javascript
jsonp原理及使用
Oct 28 Javascript
实例讲解jquery与json的结合
Jan 07 Javascript
JS图片定时翻滚效果实现方法
Jun 21 Javascript
JavaScript 网页中实现一个计算当年还剩多少时间的倒数计时程序
Jan 25 Javascript
Vue + Vue-router 同名路由切换数据不更新的方法
Nov 20 Javascript
vue-cli下的vuex的简单Demo图解(实现加1减1操作)
Feb 26 Javascript
Bootstrap fileinput 上传新文件移除时触发服务器同步删除的配置
Oct 08 Javascript
详解jQuery如何实现模糊搜索
May 10 jQuery
详解如何提升JSON.stringify()的性能
Jun 12 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删除特定数组内容并且重建数组索引的方法.
2011/03/25 PHP
php fsockopen伪造post与get方法的详解
2013/06/14 PHP
来自qq的javascript面试题
2010/07/24 Javascript
JavaScript 5 新增 Array 方法实现介绍
2012/02/06 Javascript
JavaScript数组深拷贝和浅拷贝的两种方法
2014/04/16 Javascript
详解Bootstrap四种图片样式
2016/01/04 Javascript
深入理解事件冒泡(Bubble)和事件捕捉(capture)
2016/05/28 Javascript
Javascript农历与公历相互转换的简单实例
2016/10/09 Javascript
Vue.js开发环境搭建
2016/11/10 Javascript
vue.js将unix时间戳转换为自定义时间格式
2017/01/03 Javascript
纯js实现页面返回顶部的动画(超简单)
2017/08/10 Javascript
JS排序算法之希尔排序与快速排序实现方法
2017/12/12 Javascript
在JS循环中使用async/await的方法
2018/10/12 Javascript
Vue中使用方法、计算属性或观察者的方法实例详解
2018/10/31 Javascript
vue从一个页面跳转到另一个页面并携带参数的解决方法
2019/08/12 Javascript
vue组件系列之TagsInput详解
2020/05/14 Javascript
用vue写一个日历
2020/11/02 Javascript
Vue指令实现OutClick的示例
2020/11/16 Javascript
JavaScript的一些小技巧分享
2021/01/06 Javascript
17个Python小技巧分享
2015/01/23 Python
Python程序中用csv模块来操作csv文件的基本使用教程
2016/03/03 Python
Python爬取三国演义的实现方法
2016/09/12 Python
[原创]教女朋友学Python(一)运行环境搭建
2017/11/29 Python
python网络编程:socketserver的基本使用方法实例分析
2020/04/09 Python
python获取命令行参数实例方法讲解
2020/11/02 Python
利用python进行文件操作
2020/12/04 Python
Python实现简单猜数字游戏
2021/02/03 Python
HTML5里的placeholder属性使用实例和美化显示效果的方法
2014/04/23 HTML / CSS
科颜氏加拿大官方网站: Kiehl’s加拿大
2016/08/16 全球购物
Notino罗马尼亚网站:购买香水和化妆品
2019/07/20 全球购物
什么叫应用程序域?什么是托管代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释?
2012/05/23 面试题
机关会计岗位职责
2014/04/08 职场文书
公司开除员工通知
2015/04/22 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
python全面解析接口返回数据
2022/02/12 Python
Windows server 2003卸载和安装IIS的图文教程
2022/07/15 Servers