Asmx web service returning xml instead of json, Trying to remove <string xmlns="http://tempuri.org/"> from service output
Asked Answered
N

8

9

I have been looking for 100's of links for last 3 hours eg adding scriptfactory to webconfig, 3 mistakes, setting content type etc.

I am not able to figure out what actually the mistake is.

Environment: Service running on .net 4.0 Web application running on .net 4.0

Requirements: I need to bind a jqGrid with asmx web service that is returning me a json as a string. Web service file contains following code.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public string GetJsonServerProcess()
    {
        int memory = 1;
        string json = string.Empty;
        var obj = (System.Diagnostics.Process.GetProcesses().Where(r => r.WorkingSet64 > memory).Select(p => new { p.ProcessName, p.WorkingSet64 }).ToArray());
        json = Lib.ToJSON(obj);
        return json;
    }
}

Javascript is as follows

<script type="text/javascript">
    $(document).ready(function () {
        jQuery("#jqgajax").jqGrid({
            ajaxGridOptions: { type: "POST", contentType: 'application/json; charset=utf-8'  },
            url:'http://localhost:1092/SampleService.asmx/GetJsonServerProcess',
            datatype: "json",
            data: "{}",
            colNames: ['ProcessName', 'WorkingSet64'],
            colModel: [
                        { name: 'ProcessName', index: 'ProcessName', width: 55 },
                        { name: 'WorkingSet64', index: 'WorkingSet64', width: 90 }
                    ],
            rowNum: 10,
            width: 700,
            rowList: [10, 20, 30],
            sortname: 'invdate',
            viewrecords: true,
            sortorder: "desc",
            caption: "New API Example"
        });
    });
</script>

HTML is as follows

<table id="jqgajax">
</table>
<div id="jqgajax">
</div>

Web Service output when clicking on Invoke button

<string xmlns="http://tempuri.org/">
[{"ProcessName":"Dropbox","WorkingSet64":22736896},
 {"ProcessName":"fdhost","WorkingSet64":1941504},
 {"ProcessName":"IntelliTrace","WorkingSet64":39276544}
]
</string>

Please suggest what is there that I am missing. <string xmlns="http://tempuri.org/"> tags are irritating me. I am assuming that these tags are not letting my grid able to bind.

UPDATE:

ASMX service now looks like as below.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public List<demo> GetJsonServerProcess()
    {
        List<demo> test = new List<demo>();

        for(int i=1;i<=10;i++)
            test.Add(new demo { ProcessName = string.Format("Sample {0}",i), WorkingSet64 = i });

        var re = test;
        return re;
    }
}

public class demo
{
    public string ProcessName { get; set; }
    public int WorkingSet64 { get; set; }
}
Nitza answered 30/5, 2012 at 21:23 Comment(2)
Possible duplicate:#11088794Sight
Questions are similar but solutions are different. In the linked solution, the fix was to modify the web.config file, in this solution, the fix is to modify the Content-Type header. They may not be mutually exclusive solutions though.Haywood
P
7

Clicking on the Invoke button returns XML because the request don't specify the contentType: 'application/json; charset=utf-8'. So the experiment with clicking on Invoke button help not really.

The main problem in your code is that you convert the data to string inside of web method. The line

json = Lib.ToJSON(obj);

are not needed. What one typically do is returning the object. The GetJsonServerProcess should be changed to something like

[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public List<Process> GetJsonServerProcess()
    {
        int memory = 1;
        return System.Diagnostics.Process.GetProcesses()
                   .Where(r => r.WorkingSet64 > memory)
                   .Select(p => new { p.ProcessName, p.WorkingSet64 })
                   .ToList();
    }
}

The next problem is that the default input format which wait jqGrid is another (see here). So you cave to specify jsonReader which describe the data format. In your case it will be something like

jsonReader: {
    repeatitems: false,
    id: "ProcessName",
    root: function (obj) { return obj; },
    page: function () { return 1; },
    total: function () { return 1; },
    records: function (obj) { return obj.length; }
}

Additionally you should never use http://localhost:1092/ prefix in Ajax url because you cal only get data from the same site because of security reasons. The data parameter in jqGrid has another meaning as in jQuery so you should remove data: "{}" and move type: "POST" from ajaxGridOptions to mtype: "POST". As the result you will have something like

$(document).ready(function () {
    $("#jqgajax").jqGrid({
        mtype: "POST",
        ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
        url: '/SampleService.asmx/GetJsonServerProcess',
        postData: "{}", // remove all parameters which jqGrid send typically
        datatype: "json",
        colNames: ['ProcessName', 'WorkingSet64'],
        colModel: [
            { name: 'ProcessName', index: 'ProcessName', width: 155 },
            { name: 'WorkingSet64', index: 'WorkingSet64', width: 190 }
        ],
        jsonReader: {
            repeatitems: false,
            id: "ProcessName",
            root: function (obj) { return obj; },
            page: function () { return 1; },
            total: function () { return 1; },
            records: function (obj) { return obj.length; }
        },
        rowNum: 10,
        loadonce: true,
        gridview: true,
        height: 'auto',
        rowList: [10, 20, 30],
        viewrecords: true,
        sortorder: "desc",
        caption: "New API Example"
    });
});

I don't tested the code, but it should be more close to what you need.

UPDATED: You should fix the code by changing jsonReader. You can download the working demo here. It display the grid

enter image description here

I used on the server side the code

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web.Services;

namespace jqGridWebASMX
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [System.Web.Script.Services.ScriptService]
    public class SampleService : WebService
    {
        [WebMethod]
        public List<Demo> GetJsonServerProcess()
        {
            const int memory = 1;
            return Process.GetProcesses()
                .Where (r => r.WorkingSet64 > memory)
                .Select(p => new Demo {
                    Id = p.Id,
                    ProcessName = p.ProcessName,
                    WorkingSet64 = p.WorkingSet64
                })
                .ToList();
        }
    }

    public class Demo
    {
        public int Id { get; set; }
        public string ProcessName { get; set; }
        public long WorkingSet64 { get; set; }
    }
}

and on the client side

$("#list").jqGrid({
    mtype: "POST",
    ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
    url: '/SampleService.asmx/GetJsonServerProcess',
    postData: "{}", // remove all parameters which jqGrid send typically
    datatype: "json",
    colNames: ['ProcessName', 'WorkingSet64'],
    colModel: [
        { name: 'ProcessName', index: 'ProcessName', width: 200 },
        { name: 'WorkingSet64', index: 'WorkingSet64', width: 120,
            formatter: 'integer', sorttype: 'int', align: 'right' }
    ],
    jsonReader: {
        repeatitems: false,
        id: "Id",
        root: function (obj) { return obj.d; },
        page: function () { return 1; },
        total: function () { return 1; },
        records: function (obj) { return obj.d.length; }
    },
    rowNum: 10,
    loadonce: true,
    gridview: true,
    height: 'auto',
    pager: '#pager',
    rowList: [10, 20, 30],
    rownumbers: true,
    viewrecords: true,
    sortorder: "desc",
    caption: "New API Example"
});
$("#pager_left").hide(); // hide unused part of the pager to have more space
Plainclothesman answered 30/5, 2012 at 22:1 Comment(6)
you should never use http://localhost:1092/ prefix in Ajax url currently I have created two different solutions one for services another one for web application. I have not hosted the service on IIS as of now and is directly using this service into another application for testing purpose. I was trying to implement jqGrid. So in this scenario, If I am using full path for the service Would that work?. In the live application I will take care of url. I will try all your suggestions. But It has been an hard time till now running this. Thank you for your support.Nitza
@ShantanuGupta: It's just common restriction of Ajax. The restriction is known under the name same origin policy. So you can't access another host or another port as the host or port from which you make the request. Se the prefix like http://localhost:1092/ has no sense. If you should just include web service and the correspond HTML/ASPX page on the same web server. Alternatively you can use JSONP instead of JSON, but in the case it's more complex to implements user authentication, so one use it mostly for public web services.Plainclothesman
I am still struggling with data problem. Web service is not returning JSON. It is adding XML tag on the top. <string xmlns="http://tempuri.org/">Nitza
@ShantanuGupta: Which code you use now? You get <string xmlns="http://tempuri.org/"> because you made additional serialization to JSON. So first of all you should remove second serialization and post the modified code.Plainclothesman
Please check the service code now. I have removed serialization. Can we Chat that might help me out.Nitza
@ShantanuGupta: I updated my answer. The main reason was, that one have to use root: function (obj) { return obj.d; }, records: function (obj) { return obj.d.length; } inside of jsonReader. You can download full working demo project from here.Plainclothesman
F
1

Okay, I got the same error and after a load of trial and error here's my "quick and dirty" solution;

$.get(url, {var1: parameter1, var2: parameter2}, function(data){
    data = JSON.parse($(data).find("string").text());
    alert("data.source: " + data.source);
});
Forgetful answered 13/8, 2013 at 10:8 Comment(0)
R
1

The following code should do the trick:

this.Context.Response.ContentType = "application/json; charset=utf-8";
this.Context.Response.Write(json);
Rottenstone answered 1/7, 2016 at 13:58 Comment(0)
I
1

This code works perfectly

SqlDataAdapter sda = new SqlDataAdapter(strsql, ConfigurationManager.ConnectionStrings["BTConString"].ToString());
DataSet das = new DataSet();
sda.Fill(das);
Context.Response.Output.Write(JsonConvert.SerializeObject(das, Newtonsoft.Json.Formatting.Indented));
Context.Response.End();

return string.Empty;
Indecorum answered 21/6, 2017 at 7:16 Comment(1)
How does this contribute to a 5 year old question with an accepted answer? .... Not very much...Imogeneimojean
A
0
  response = await client.GetAsync(RequestUrl, HttpCompletionOption.ResponseContentRead);
                if (response.IsSuccessStatusCode)
                {
                    _data = await response.Content.ReadAsStringAsync();
                    try
                    {
                        XmlDocument _doc = new XmlDocument();
                        _doc.LoadXml(_data);
                        return Request.CreateResponse(HttpStatusCode.OK, JObject.Parse(_doc.InnerText));
                    }
                    catch (Exception jex)
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest, jex.Message);
                    }
                }
                else
                    return Task.FromResult<HttpResponseMessage>(Request.CreateResponse(HttpStatusCode.NotFound)).Result;
Alible answered 17/5, 2015 at 10:19 Comment(0)
L
0

Before function starts put the below

[System.Web.Services.WebMethod(EnableSession = true)]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]

make function as void

when the function ends put below line

this.Context.Response.ContentType = "application/json; charset=utf-8";
this.Context.Response.Write(json);

Example program

        [System.Web.Services.WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
        public void testJson()
        {
            string json = "{}";
            this.Context.Response.ContentType = "";
            this.Context.Response.Write(json);
        }
Lactobacillus answered 7/5, 2019 at 6:42 Comment(0)
A
0

You can put your url in postman and use the response

Like this i am using php

<?php

$curl = curl_init();

curl_setopt_array($curl, array( CURLOPT_URL => 'your url', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', ));

$response = curl_exec($curl);

curl_close($curl); echo $response;

?>
Ahner answered 5/12, 2020 at 7:12 Comment(0)
E
-1

For Valid JSON response use this code..

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public void GetJsonServerProcess()
    {
        int memory = 1;
        string json = string.Empty;
        var obj = (System.Diagnostics.Process.GetProcesses().Where(r => r.WorkingSet64 > memory).Select(p => new { p.ProcessName, p.WorkingSet64 }).ToArray());
        json = Lib.ToJSON(obj);
       this.Context.Response.ContentType = "application/json; charset=utf-8";
            this.Context.Response.Write(json);

    }
}
Equiangular answered 18/7, 2015 at 10:55 Comment(1)
Please write what you done, and how it useful to the problem.Thoreau

© 2022 - 2024 — McMap. All rights reserved.