Возврат 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 ответов:
Мне кажется, что ваша главная проблема в том, что вы пытаетесь вручную использовать
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 варианта:
- Используйте объект DTO
- Напишите свой собственный специфический конвертер сериализации
У меня плохой английский, но это решение
----- 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>