ASP.NET WebService обертывает мой ответ JSON тегами XML

Я не уверен, где я ошибаюсь в том, чего не хватает.

Я создаю веб-приложение ASP.NET 2.0 (на веб-приложении .Net 3.5), и я включаю веб-сервис. Обратите внимание, что это не проект MVC. Я хочу выставить метод, который вернет строку JSON; отформатированный для подачи плагина jqGrid jQuery.

Это предварительный метод тестирования, который я реализовал в своем сервисе: благодаря (Руководство по Phil Haack для MVC)

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string getData()
{
    JavaScriptSerializer ser = new JavaScriptSerializer();

    var jsonData = new
    {
        total = 1, // we'll implement later 
        page = 1,
        records = 3, // implement later 
        rows = new[]{
          new {id = 1, cell = new[] {"1", "-7", "Is this a good question?", "yay"}},
          new {id = 2, cell = new[] {"2", "15", "Is this a blatant ripoff?", "yay"}},
          new {id = 3, cell = new[] {"3", "23", "Why is the sky blue?", "yay"}}
        }
    };

    return ser.Serialize(jsonData); //products.ToString();
}

При вызове возвращается (форматируется для ясности):

<?xml version="1.0" encoding="utf-8" ?> 
<string  mlns="http://tempuri.org/">
{
  "total":1,
  "page":1,
  "records":3,
  "rows":
    [
      {"id":1,"cell":["1","-7","Is this a good question?","yay"]},
      {"id":2,"cell":["2","15","Is this a blatant ripoff?","yay"]},
      {"id":3,"cell":["3","23","Why is the sky blue?","yay"]}
    ]
}
</string> 

Как я мог бы выполнить вышеупомянутый ответ без оберток xml?

Ответ 1

Три вещи, которые вы не можете делать:

  • Пометка метода static
  • Выполнение POST
  • Передайте пустое значение "{}" для данных в jQuery.

Может быть способ вызова метода с помощью GET, я использовал POST только когда-либо. Я смог заставить ваш пример работать с этим:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
    // In your javascript block
    $(document).ready(function()
    {
        $.ajax({
            url: "/Default.aspx/Tester",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: "{}",
            success: done
        });
    });

    function done(data)
    {
        // Include http://www.json.org/json2.js if your browser doesn't support JSON natively
        var data = JSON.parse(data.d);
        alert(data.total);
    }
</script>

Код позади (вам не нужно создавать веб-сервис, вы можете поместить его в default.aspx):

[WebMethod]
public static string Tester()
{
    JavaScriptSerializer ser = new JavaScriptSerializer();

    var jsonData = new
    {
        total = 1, // we'll implement later 
        page = 1,
        records = 3, // implement later 
        rows = new[]{
              new {id = 1, cell = new[] {"1", "-7", "Is this a good question?", "yay"}},
              new {id = 2, cell = new[] {"2", "15", "Is this a blatant ripoff?", "yay"}},
              new {id = 3, cell = new[] {"3", "23", "Why is the sky blue?", "yay"}}
            }
        };

    return ser.Serialize(jsonData); //products.ToString();
}

Результат:

{"d":"{\"total\":1,\"page\":1,\"records\":3,\"rows\":[{\"id\":1,\"cell\":[\"1\",\"-7\",\"Is this a good question?\",\"yay\"]},{\"id\":2,\"cell\":[\"2\",\"15\",\"Is this a blatant ripoff?\",\"yay\"]},{\"id\":3,\"cell\":[\"3\",\"23\",\"Why is the sky blue?\",\"yay\"]}]}"}

Более подробное объяснение здесь

Ответ 2

В вашем коде не возвращайте json. Вместо этого используйте

Context.Response.Write(ser.Serialize(jsonData));

Тогда вы будете хороши.

Регулярная команда возврата помогает вам, добавив более правильный формат обслуживания. Кто-то сказал бы, что лучше использовать эту возможность и развернуть свой json на клиенте из этого формата. Я говорю, просто плюньте на то, как вы хотите его использовать!

Ответ 3

Когда вы отмечаете службу как ScriptService, она автоматически обрабатывает сериализацию JSON. Вы не должны вручную сериализовать ответ. Подробнее см. этот элемент.

Ответ 4

Если вы запрашиваете JSON, и если вы включаете атрибут [ScriptService], ASP.NET автоматически сериализует ответ на JSON. То, что вы видели XML, предполагает, что одна из этих двух предварительных условий не выполняется. Рекомендации по сериализации для JSON вручную неправильны, если вы не хотите использовать другой сериализатор, такой как Newtonsoft.

Вот простой рабочий пример веб-службы ASMX с поддержкой JSON:

<%@ WebService Language="C#" Class="WebService" %>
using System;
using System.Collections.Generic;
using System.Web.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
    [WebMethod]
    public MyClass Example()
    {
        return new MyClass();
    }

    public class MyClass
    {
        public string Message { get { return "Hi"; } }
        public int Number { get { return 123; } }
        public List<string> List { get { return new List<string> { "Item1", "Item2", "Item3" }; } }
    }
}

JavaScript, чтобы запросить его и обработать ответ (мы просто выставим предупреждение JS с сообщением из MyClass.Message):

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Test</title>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.4.js" type="text/javascript"></script>  
</head>
<body>
    <script type="text/javascript">
        $.ajax({
            type: "POST",
            url: "WebService.asmx/Example",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: "{ }",
            error: function (XMLHttpRequest, textStatus, errorThrown) { alert(langError + " " + textStatus); },
            success: function (msg) {
                alert(msg.d.Message);
            }
        });
    </script>
</body>
</html>

Запрос Http:

POST http://HOST.com/WebService.asmx/Example HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Referer: http://HOST.com/Test.aspx
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Connection: Keep-Alive
Content-Length: 3
Host: HOST.com

{ }

HTTP-ответ:

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 08 Oct 2013 08:36:12 GMT
Content-Length: 98

{"d":{"__type":"WebService+MyClass","Message":"Hi","Number":123,"List":["Item1","Item2","Item3"]}}

Результат:

"Привет" отображается в всплывающем окне JS.

См. также:

fooobar.com/questions/463778/...

fooobar.com/questions/90668/...

Ответ 5

Мне повезло, что я сделал следующее:

[WebMethod]
public static void GetDocuments()
{
    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject(repository.GetDocuments()));
    HttpContext.Current.Response.End();
}

Важно правильно установить тип контента и написать JSON непосредственно для ответа, а затем завершить ответ так, чтобы дальнейшие данные не были отправлены, чтобы повредить ваш ответ. Преимущество этой архитектуры заключается в том, что вы можете использовать любой необходимый вам сериализатор, вы не ограничены встроенным JSON-сериализатором. В этом случае я использовал Json.NET.

Я понимаю, что это злоупотребление архитектурой (и мне лично не нравится иметь тип возврата void для чего-то, что должно возвращать данные), но это единственный действительно надежный метод, который я нашел.

С другой стороны, вы должны переключиться на WCF или Web API, по причинам, которые Джон Сондерс описывает здесь. Веб-API, в частности, очень прост в использовании и допускает согласование типов контента между клиентом и сервером.

Ответ 6

  1. сделать тип возврата недействительным
  2. поместите свой объект на ^ _ ^
[WebMethod]
public static void GetDocuments()
{
    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject( ^_^ ));
    HttpContext.Current.Response.End();
}

Ответ 7

[WebMethod]
public static void GetDocuments()
{
    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject(repository.GetDocuments()));
    HttpContext.Current.Response.End();
}