在跟html+ashx打交道的园友们肯定会发现,这种模式虽然优美,但在开发中会遇到一些难处理的地方。我也不例外,下面是自己在实际开发中总结出来的几条经验,希望跟大家分享,更希望得到大家的建议和更好的解决方法!
 

问题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对象只是为了阅读方便,然而用到这如此合适!到这的时候我已兴奋不已了,测试结果如下:


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

关于html+ashx开发中几个问题的解决方法的更多相关文章

  1. 关于html+ashx开发中几个问题的解决方法 (转)

    在跟html+ashx打交道的园友们肯定会发现,这种模式虽然优美,但在开发中会遇到一些难处理的地方.我也不例外,下面是自己在实际开发中总结出来的几条经验,希望跟大家分享,更希望得到大家的建议和更好的解 ...

  2. 关于html+ashx开发中几个问题的解决方法的感想和总结

    1.针对上篇文章中的服务端处理不敢苟同.仍然坚持使用反射,建立BaseHandler.ashx并在默认process方法中写上反射方法以及权限验证方法.针对具体的情况返回对应的值.服务端其他handl ...

  3. java开发中遇到的问题及解决方法(持续更新)

    摘自 http://blog.csdn.net/pony12/article/details/38456261 java开发中遇到的问题及解决方法(持续更新) 工作中,以C/C++开发为主,难免与其他 ...

  4. 浅谈Excel开发:九 Excel 开发中遇到的常见问题及解决方法

    Excel开发过程中有时候会遇到各种奇怪的问题,下面就列出一些本人在开发中遇到的一些比较典型的问题,并给出了解决方法,希望对大家有所帮助. 一 插件调试不了以及错误导致崩溃的问题 在开发机器上,有时可 ...

  5. 安卓开发中Theme.AppCompat.Light的解决方法

    styles.xml中<style name="AppBaseTheme" parent="Theme.AppCompat.Light">提示如下错 ...

  6. 微信小程序在开发中遇到的问题与解决方法

    1.  √ 这种错误多半是该js文件中没有Page这个方法,就算是空的js也必须要把Page({ })写上去 2.  √ 这种错误多半是该json文件没有内容,所以必须要加上{ },就算是空内容也要加 ...

  7. phpcms模块开发中的小问题及解决方法

    1.模块菜单中文名出错 在编写安装模块时候可能需要更改extention.inc.php中定义中文名称,由于反复安装或者通过phpcms的扩展->菜单管理 修改菜单名会导致中文名失败.解决办法很 ...

  8. VC6.0开发中一些链接错误的解决方法

    (1)error LNK2001: unresolved external symbol _main 编号:LNK2001 直译:未解决的外部符号:_main. 错误分析:缺少main函数.看看mai ...

  9. 移动Web开发中遇见的问题以及解决方法(不断更新中)

    20160524 问题:在使用des加密数据后,作为url参数传递发现,系统会把+自动变为空格,以至于解密的时候出现问题. 例如:uKsRUwdU6+83+J9WfgfflA== 传到服务端后 变为u ...

随机推荐

  1. Python系列之 - 面向对象(1)

    python是一门面向对象的编程语言,python中的一切均是对象. 有对象就提到类,对象和类就像是儿子和老子的关系,是不可分的一对. 什么是类     类就是具有一些共同特性的事物的统称.好比人类, ...

  2. CSS属性操作

    CSS属性操作 1 属性选择器 Elenment(元素) E[att] 匹配所有具有att属性的E元素,不考虑它的值.(注意:E在此处可以省略)(推荐使用) 例如:[po]{ font-size: 5 ...

  3. Linux下wget获取ftp下目录下文件

    如果某个目录下有一个文件可以使用ftp命令: get xxx 如果是某个目录下有多个文件(且不需要获取目录下子文件夹下的内容): mget * 如果是某个目录下有子目录希望获取所有子目录: wget ...

  4. scrollTop doesn't scroll on Chrome 61

    在chrome61 不支持滚动 解决方案: Use document.scrollingElement if supported, and fall back to the current code. ...

  5. PHP多个一维数组合并成二维数组的简易方法

    当我们需要进行数组遍历数据的时候,需要将多个一维数组进行二维的转换,方法很简单.如下: <?php $a= array('张三','李四','王五'); $b= array ('23','24' ...

  6. 学习React系列(一)——React.Component 生命周期

    挂载中(只执行一次) 以下方法在组件实例正被创建和插入到DOM中时调用 constructor()一般用于初始化state和方法的this绑定 componentWillMount() render( ...

  7. 基于vue2.0的一个系统

    前言 这是一个用vue做的单页面管理系统,这里只是介绍架子搭建思路 前端架构 沿用Vue全家桶系列开发,主要技术栈:vue2.x+vue-router+vuex+element-ui1.x+axios ...

  8. 音频压缩编码 opus 附完整C++代码示例

    绝大数人都知道mp3格式编码,以及aac,amr等压缩格式编码. 而在语音通信界有一个强悍的音频格式编码opus. 经过实测,压缩比最高可以达到1:10. 100KB 压缩后 10KB 虽然是有损压缩 ...

  9. OpenGL平面阴影

    几种绘制阴影的方法 在OpenGL中,比较常见的绘制阴影的方法有:shadow mapping,shadow volumes以及一种在红宝书上提及的适合在确定平面上绘制阴影的方法. 平面阴影 在确定的 ...

  10. [LeetCode] Maximum Width of Binary Tree 二叉树的最大宽度

    Given a binary tree, write a function to get the maximum width of the given tree. The width of a tre ...