一种开发模式:ajax + ashx + UserControl

1、ajax+ashx模式的缺点

    在web开发过程当中,为了提升网站的用户体验,或多或少都会用到ajax技术,甚至有的网站所有采用ajax来实现,大量使用ajax在加强用户体验的同时会带来一些负面影响,好比:不利于seo;然而,对于asp.net来讲,通常会采用ashx文件做为ajax调用的后台,这种状况下,每一个ajax请求都会对应一个ashx页面,若是请求过多则会形成项目中有繁多的ashx文件,不利于管理与维护,那么怎样改善这种状况呢?

2、问题分析与改进(反射)

    经过分析发现,每一个ajax调用ashx的步骤都是同样,都分为如下三步:
    一、解析请求中的用户数据
    二、处理用户请求
    三、返回处理结果
    这三个步骤中,第一和第三步对于每一个请求来讲都同样,只有第二部涉及到数据的具体处理,每一个请求会有所不一样,所以须要针对第二个方面进行改进。
    ashx文件的类做为一个Handler,它是继承于IHttpHandler接口的,在处理业务时,每一个请求都会首先进入方法"ProcessRequest"中,为了减小ashx文件的数量,咱们能够将同一模块中的操做放在一个ashx文件中进行处理,具体代码相似下面中这样:
    
public void ProcessRequest(HttpContext context)
    {
        // 一、解析请求参数,此处忽略
        // 二、如下为具体处理方式
        string returnString = string.Empty;
        string methodName = context.Request.Form["methodName"];
        switch(methodName)
            case "GetData":
                returnString = GetData();
                break;
            case "InsertNewRow"
                returnString = InsertNewRow();
                break;
            .....等等多个case分支
            default:
            break;
        // 三、向客户端返回结果        
        context.Response.Write(returnString);
    }

 

    这种方式经过在用户请求中添加一个用来代表具体调用方法的参数,能够将同一模块中的操做所有放在一块儿,并经过switch语句进行判断,而后分别调用,这样能够减小必定数量的ashx文件。可是这种方式存在一个弊端,若是方法不少的话会形成switch语句出现大量的分支,而且每一个ashx文件中都须要在ProcessRequest方法中进行相同业务逻辑判断,那么怎样将这些相同的行为进行改进呢?咱们知道,请求中包含了须要调用的方法名,为了将这些方法的调用进行统一处理,显然咱们能够利用反射。
    经过定义一个Handler基类,让其余全部的ashx类继承此Handler,具体的处理方法写在子类中,这样基类的功能就能够简化为以下形式:
    
//Handler基类中的方法,为全部的Handler子类的方法进行调度
public void ProcessRequest(HttpContext context)
    {
        // 一、解析请求参数,此处忽略其余参数的解析,仅获取方法名
        string methodName = context.Request.Form["Action"];
        // 二、如下为反射的具体处理方式
        Type type = this.GetType();
        Object[] params = new Objece[1];  //方法参数,咱们统一将context做为参数,觉得用户数据都封装在其中
        MethodInfo method = type.GetMethod(methodName);
        string returnString = (string)method.Invoke(this,params);
        // 三、向客户端返回结果        
        context.Response.Write(returnString);
    }

public String GetRequest(HttpContext context, String paramName)
{
    if (context.Request[paramName] != null)
    {
        return context.Request[paramName].ToString();
    }javascript

     return "";html

}java

 
  
 
而后,继承该Handler的子类只须要实现具体的处理方法便可,该基类能够统一为全部子Handler进行方法调度,不再会出现可能会愈来愈臃肿的switch,该方式相似于mvc中的controller调度,经过action来进行判断
    下面是一个子Handler的示例:
/// <summary>
    /// UserHandler 的摘要说明
    /// </summary>
    public class UserHandler : BaseHandler
    {
        /// <summary>
        /// 用户登陆处理
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public String Login(HttpContext context)
        {
            String strAccount = "";
            String strPassword = "";
            String strRet;

            try
            {
                //获取页面传值
                strAccount = GetRequest(context, "Account");
                strPassword = GetRequest(context, "Password");

                if (strAccount != "" && strPassword != "")
                {
                    //简单起见,仅返回传递过来的用户帐号与密码
                    //在实际应用中利用传递过来的参数值调用业务逻辑层的方法来完成客户端的请求
                    strRet = String.Format("帐号:{0},密码:{1}", strAccount, strPassword);
                }
                else
                {
                    //返回提示信息
                    strRet = "未能正确获取参数!";
                }


                return strRet;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        
    }

 

前台调用代码以下:
<script type="text/javascript">
        $(document).ready(function () {
            $("#btnLogin").click(function () {
                var account;
                var password;

                account = $("#txtUserName").val();
                password = $("#txtPassword").val();

                $.ajax({
                    type: "POST",
                    async: true,
                    url: "Handler/UserHandler.ashx",
                    dataType: "text",
                    data: { Action: "Login", Account: account, Password: password },
                    success: function (data) {
                        alert(data);
                    },
                    error: function (xhr) {
                        alert(xhr.statusText);
                        return false;
                    }
                });
            });
        });
    </script>

 


    至此,已经完成了ajax + ashx开发模式的改进,可是仍然存在一下两个问题:
    一、由于采用了ajax技术,因此在提交请求时须要手动封装表单中的数据,若是数据过多,封装过程比较繁琐
    二、在输出时须要大量拼接html字符串,这也是一个繁琐的活

3、ajax请求中表单数据的封装

    为了提升数据的封装效率,咱们可使用jquery.form.js插件,该插件提供了便利的操做,能够根据须要封装表单中的所有或者部分数据,使用起来十分简单。
,下面说一下UserControl的用法

4、利用UserControl进行html输出

    在ajax+ashx处理方式中,大部分状况下都须要进行html字符的拼接,这种拼接很是繁琐却又不得不作,若是是很是简短的字符串还倒能够,若是遇到大量数据的显示,恐怕单单这一项任务就够让人烦的了,这里咱们能够利用用户控件(UserControl)来帮咱们完成html的呈现,具体思路以下:
    定义一个视图控制器类(ViewManage),专门用来建立用户控件的实例和生成用户控件的html,该试图控制器内部主要经过定义一个空的Page类,而后将该用户控件加载到Page中建立其实例,而后将Page对象的整个生命周期运行一遍,并将结果html输出。
    经过用户控件输出html还不会影响页面的SEO,由于在客户端<a/>的href仍是有效的
 

总结:

该开发模式在利用ajax的同时,采用 "控制器+反射" 的模式进行方法调度,利用form插件来进行表单数据封装,对于大数据量的输出利用"用户控件"进行html生成。
对于ajax与SEO,须要遵循如下几点:
一、AJAX、SEO同等重要,在同一个WEB项目中为他们各自选择合适的使用领域。
二、会员管理、账户中心、购物车、后台管理等操做界面可使用AJAX,以提升用户体验和UI交互。
三、网站前台展现的页面,如新闻内容、商品介绍、帮助、文档类页面,不要使用AJAX,以SEO为主。
四、当咱们认清楚AJAX何时该用,何时不应用,一个网站的SEO与AJAX技术结合就变得很简单了。
相关文章
相关标签/搜索