问题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文件里(最下面)是一个可行的方法:
复制代码 代码如下: