ASHX调用JSON过程容易出现返回页面和无数据返回的解决方法

时间:2021-11-11 15:50:40
其实也不是什么解决方法,就是在使用JS调用ASHX返回JSON时对返回值的要求严格要求,我接连二次犯这样的错误,而在网上搜到的解决方案均未说明原因。
查在公示给大家,以免大家辛苦了。

JSON格式值部分必须的是字符串,特别是使用SQL时,另外,不要过多写SQL语句来提数据,只好是使用视图来完成数据的一级提取。
之前我写了一段指令,最后被近换成了这样。
select *  from 视图  where id=cast(@id as int) 

现将JS 调用ASHX代码公示如下:

JS部分:

  

  function xs_xsqk() {
        var arr_s1 = "";
        var xhr_xsqk = new XMLHttpRequest();
        //设定请求对象和后台哪个页面进行交互
        xhr_xsqk.open("get", "Handler_xsqk.ashx?kpid=<%=Session["title_kpid"].ToString()%>", true);
        //发送请求
        xhr_xsqk.send();
        //后台返回数据后,会调用此方法(回调函数)
        xhr_xsqk.onreadystatechange = function (data) {
            if (xhr_xsqk.readyState == 4) {
                //alert(xhr_xsqk.responseText);
                arr_s1 = eval("(" + xhr_xsqk.responseText + ")");               
                data1 = JSON.parse(arr_s1);
                $.each(data1, function (index, item) {
                    $("#Label1").html(item.s1);
                    $("#Label2").html(item.s2);
                    $("#Label3").html(item.s3);
                    $("#Label4").html(item.s4);
                    $("#Label5").html(item.s5);
                });
            };
        };
    }



ASHX代码

        Operation Operation = new Operation();
        DataSet data_dyid = new DataSet();
        public static string kpid;
        public void ProcessRequest(HttpContext context)
        {
            kpid = context.Request["kpid"].ToString();
            data_dyid = Operation.data_zxkp_xsqk(kpid);
            DataTable dt = data_dyid.Tables[0];

            string callback = context.Request["callback"];

            context.Response.Clear();
            context.Response.ContentType = "application/json"; //text/plain                  
            string jsonstring = datatabletojson(dt);
            context.Response.Write(callback + "('" + jsonstring + "')");

        }

 
        private string datatabletojson(DataTable dt)
        {
            List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
            foreach (DataRow row in dt.Rows)
            {
                Dictionary<string, object> dict = new Dictionary<string, object>();
                foreach (DataColumn col in dt.Columns)
                {
                    dict[col.ColumnName] = row[col];

                }
                list.Add(dict);
            }
            JavaScriptSerializer jss = new JavaScriptSerializer();
            return jss.Serialize(list);


        }




SQL数据提取部分:



    public DataSet data_zxkp_xsqk(string kpid)
    {
        SqlParameter[] parms1 = {
                               data.MakeInParam("@kpid",SqlDbType.NVarChar,10,kpid),
                               };
        return data.RunProcReturn("select *  from v_zxkp_xsqk where kpid=cast(@kpid as int) ", parms1, "data_zxkp_xsqk");
    }
    #endregion




4 个解决方案

#1


看了半天没看明白你想表达什么。
容易出现:返回页面和无数据返回???
那你有没有分析产生这种问题的原因???
       分析为什么会返回页面?那是因为服务器对你的请求的处理并没有以正常的方式进行;它自动返回一个含有提示信息的页面给你啊。
       分析为什么会无数据?那还不是你服务端根本就返回的是空数据吗??

在ajax和服务端交互的时候,你可以定义一种固定的消息格式。类似这样的:
        在服务端处理一切正常的时候,返回的消息:{"status":1,msg:"请求成功",data:‘数据’}
        在服务端处理不正常的时候 ,返回的消息:{"status":2,msg:"请求失败",data:‘’}
然后在客户端对不同的消息进行判断、处理。

当然,在客户端也可以根据 http响应状态码来判断,做出你认为正确的处理

#2


那 sql 查询结果弄成 datatable,然后又序列化,这是多此一举。你可以直接将查询写成匿名强类型的对象集合,例如基于扩展方法
    public static List<T> ExecuteList<T>(this DbCommand cmd, Func<IDataRecord, T> converter)
    {
        using (var rd = cmd.ExecuteReader())
            return (from IDataRecord r in rd select converter(r)).ToList();
    }
那么直接写
var result = dbcommand..ExecuteList<string>(x => new 
{
    A = (string)x[0],
    B = (int)x[1],
    X = (DateTime)x["field_x"]
}
这样就行了。用不着什么 DataTable、DataSet之类的对象类。

#3


嗯,上面多写了一个<....>,应该是
var result = dbcommand..ExecuteList(x => new 
{
    A = (string)x[0],
    B = (int)x[1],
    X = (DateTime)x["field_x"]
}

c# 会自动进行类型推断,所以 ExecuteList 使用时根本不需要写尖括号中间的东西。

#4


你还可以写一个处理 DBNull 值的扩展方法,例如
    public static T GetValue<T>(this IDataRecord reader, string fieldName)
    {
        var x = reader[fieldName];
        if (x == DBNull.Value)
            return default(T);
        else
            return (T)x;
    }
它可以处理掉数据库中的空值,那么上面的查询就可以改为
var result = dbcommand..ExecuteList(x => new 
{
    A = x.GetValue<string>(x[0]),
    B = (int)x[1],
    X = x.GetValue<DateTime>("field_x")
});

你基于 List<T> 编程,比 DataTable 强。

#1


看了半天没看明白你想表达什么。
容易出现:返回页面和无数据返回???
那你有没有分析产生这种问题的原因???
       分析为什么会返回页面?那是因为服务器对你的请求的处理并没有以正常的方式进行;它自动返回一个含有提示信息的页面给你啊。
       分析为什么会无数据?那还不是你服务端根本就返回的是空数据吗??

在ajax和服务端交互的时候,你可以定义一种固定的消息格式。类似这样的:
        在服务端处理一切正常的时候,返回的消息:{"status":1,msg:"请求成功",data:‘数据’}
        在服务端处理不正常的时候 ,返回的消息:{"status":2,msg:"请求失败",data:‘’}
然后在客户端对不同的消息进行判断、处理。

当然,在客户端也可以根据 http响应状态码来判断,做出你认为正确的处理

#2


那 sql 查询结果弄成 datatable,然后又序列化,这是多此一举。你可以直接将查询写成匿名强类型的对象集合,例如基于扩展方法
    public static List<T> ExecuteList<T>(this DbCommand cmd, Func<IDataRecord, T> converter)
    {
        using (var rd = cmd.ExecuteReader())
            return (from IDataRecord r in rd select converter(r)).ToList();
    }
那么直接写
var result = dbcommand..ExecuteList<string>(x => new 
{
    A = (string)x[0],
    B = (int)x[1],
    X = (DateTime)x["field_x"]
}
这样就行了。用不着什么 DataTable、DataSet之类的对象类。

#3


嗯,上面多写了一个<....>,应该是
var result = dbcommand..ExecuteList(x => new 
{
    A = (string)x[0],
    B = (int)x[1],
    X = (DateTime)x["field_x"]
}

c# 会自动进行类型推断,所以 ExecuteList 使用时根本不需要写尖括号中间的东西。

#4


你还可以写一个处理 DBNull 值的扩展方法,例如
    public static T GetValue<T>(this IDataRecord reader, string fieldName)
    {
        var x = reader[fieldName];
        if (x == DBNull.Value)
            return default(T);
        else
            return (T)x;
    }
它可以处理掉数据库中的空值,那么上面的查询就可以改为
var result = dbcommand..ExecuteList(x => new 
{
    A = x.GetValue<string>(x[0]),
    B = (int)x[1],
    X = x.GetValue<DateTime>("field_x")
});

你基于 List<T> 编程,比 DataTable 强。