Возврат JSON из ASMX и корректная обработка его в Javascript


Я понимаю, что здесь уже есть тонны подобных вопросов, но я не могу понять этот.

У меня есть веб-сервис (C#, .net 3.5). Основной код, который вам нужно знать, заключается в следующем:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WSMember : System.Web.Services.WebService {

    public WSMember () {   
    }


    [WebMethod]
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public string GetMember(string IdMember)
    {
        //Ignore the parameter for now... I will be looking up a database with it... 
        //For now just return a minimal object:
        Member m = new Member();
        m.Surname = "Smith";
        m.FirstName = "John";
        return new JavaScriptSerializer().Serialize(m);
    }

Также, в сети.config, я сделал следующее дополнение (которое я только что видел на каком-то другом посте... это нормально/безопасно?)

  <webServices>
      <protocols>
        <add name="HttpGet" />
        <add name="HttpPost" />
      </protocols>
    </webServices>

Тогда по умолчанию.aspx, я две ключевые ссылки...

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script type="text/javascript" src="jquery.json-2.2.min.js"  ></script>

Jquery.в JSON-2.2.минута.js был загружен из google код

А вот и Javascript:

<script type="text/javascript">
         $(document).ready(function() {
             $("#button1").click(function(event) {
                 var myData = { IdMember: "2" };
                 var encoded = $.toJSON(myData);

                 alert(encoded);

                 $.ajax({
                     type: "POST",
                     url: "WSMember.asmx/GetMember",
                     data: encoded,
                     contentType: "application/json; charset=utf-8",
                     dataType: "json",
                     success: function(msg) {
                         alert("worked" + msg.d);
                         //$("#sidebar").append(msg);
                     },
                     error: function(msg) {
                         alert(msg.d);
                         //$("#sidebar").append(msg);
                     }
                 });
             });
         });

    </script>

Когда я выполняю его, кодированный json появляется в окне сообщения, как и ожидалось... то есть с двойными кавычками:

{"IdMember": "2"}

Однако

, он всегда терпит неудачу. Даже для самого простого Hello World без передачи данных, он не работает. Я продолжаю получать "неопределенный" для данных сообщения.

Если я просто использую alert (msg), он отображает [object XMLHttpRequest]

Кто-нибудь знает, куда попадают мои данные заблудился??

И еще один вопрос... есть ли что-то фундаментально неправильное в том, что я делаю?

Большое спасибо.

Редактировать:

Спасибо за ответ, ребята. Я попробовал следующее Так...

UseHttpGet = true теперь заменено на false. (Опять-таки, я где-то это видел и попробовал... но я знал, что это не может быть правильно : -/)

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

    StringBuilder sb = new StringBuilder();
    sb.Append("{");
    sb.Append(""Surname":");
    sb.Append(""");
    sb.Append(m.Surname);
    sb.Append(""");

    sb.Append(","FirstName":");
    sb.Append(""");
    sb.Append(m.FirstName);
    sb.Append(""");

    sb.Append("}");

    return sb.ToString();

Этот код возвращает что-то вроде:

{"Surname":"Smith","FirstName":"John"}

Я все еще получаю точно такую же ошибку...

Я также попробовал что-то вроде возврата объекта "Member", поэтому код становится:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public Member GetMember(string IdMember)
{
    Member m = new Member();
    m.Surname = "Smith";
    m.FirstName = "John";

    return m;
}

Это тоже приводит к той же ошибке.

Прости, что причиняю тебе боль... Я читал обе эти ссылки и другие. Просто не могу понять, чем это отличается.

Есть ли какие-либо дополнительные настройки конфигурации, о которых мне нужно знать возможно??

Большое спасибо за ответы.

Обновление: Проблема решена. Ключевые ошибки в приведенном выше коде:

[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]

Должно быть

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

Кроме того, на форме, при использовании кнопки для вызова javascript, я неправильно устанавливал тип ввода...

<input id="button1" type="submit" value="Just a test" />

Когда он должен сказать:

<input id="button1" type="button" value="Just a test" />

Большое спасибо всем, кто помог.

5 7

5 ответов:

Мне кажется, что ваша главная проблема в том, что вы пытаетесь вручную использовать JavaScriptSerializer().Serialize вместо возврата объекта. Ответ от веб-сервиса будет двойная разметка JSON.

Вы правы! Есть много близких вопросов. Посмотрите здесь Могу ли я вернуть JSON из an .веб-служба asmx, если ContentType не является JSON? и не удается получить jQuery Ajax для разбора результата JSON webservice, и вы (я надеюсь) найдете ответ.

Обновлено : Извините, но у вас есть небольшая ошибка где-то, что вы не разместили. Чтобы закрыть эту проблему, я создал небольшой проект со старой версией Visual Studio (VS2008), которая имеет практически точно ваш код и которая работает. Я поставил его на http://www.ok-soft-gmbh.com/jQuery/WSMember.zip вы можете скачать его, скомпилировать и проверить, что он работает. Затем вы можете сравнить свой код с моим и найти свою ошибку.

С наилучшими пожеланиями

Если вы делаете запись для своих данных, почему вы определяете UseHttpGet = true? Разве это не должно быть ложью, чтобы соответствовать типу ответа из вашего запроса? Кроме того, установка точки останова в вызове ws, чтобы точно увидеть, что возвращает сериализатор, также поможет... Я не думаю, что он должен возвращать объект JSON, если возвращаемое значение является строкой.

HTH.

Да, определенно не сериализуйте объект вручную. Если вы возвращаете тип Member, платформа будет обрабатывать сериализацию JSON для вас.

Когда вы видите предупреждение [object XMLHttpRequest], это звучит так, как будто оно попадает в обработчик ошибок в вашем $.вызов ajax (), где ответ передается в свой объект XHR в качестве первого параметра. Вы, вероятно, получаете ошибку 500 на сервере.

Вот пример декодирования ASP.NET AJAX error response in jQuery . Проще всего, измените обработчик ошибок следующим образом:

error: function(xhr, status, error) {
  var err = eval("(" + xhr.responseText + ")");

  alert(err.Message);
}
Это даст вам некоторое представление о том, что такое конкретная ошибка.

Если вы возвращаете любой сложный объект (реляционные объекты с внешними ключами), у вас есть 2 варианта:

  1. Используйте объект DTO
  2. Напишите свой собственный специфический конвертер сериализации

У меня плохой английский, но это решение

----- WSMember.asmx - - - - - -

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WSMember : System.Web.Services.WebService {

     public WSMember () {   
     }

     [WebMethod]
     [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
     public string GetMember(int IdMember)
     {
         Member m = new Member();//Get Member from DB, exam Linq to Sql
         m.Surname = "Smith";
         m.FirstName = "John";
         return string.Format("{{ \"Surname\":\"{0}\",\"FirstName\":\"{1}\" }}",m.Surname,m.FirstName);
     }
}

- - - - по умолчанию.aspx - - - -

<a href="#" id="button1">Just a test</a>
<script type="text/javascript">
    $("#button1").click(function (event) {
        event.preventDefault();
        $.ajax({
            type: "POST",
            url: "WSMember.asmx/GetMember",
            data: "{IdMember: 2 }",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {
                if (msg.hasOwnProperty('d')) {
                    msg = msg.d;
                }
                var json = JSON.parse(msg);
                console.log(json.Surname);
                console.log(json.FirstName);
            },
            error: function (xhr, status, error) {
                //console.log(xhr);
                //console.log(status);
                //console.log(error);
            }
        });
    });
</script>