Это вопрос из двух частей:
1) Что является лучшим подходом, позволяя .NET преобразовывать собственные объекты в JSON или использовать обертки и кодировать их самостоятельно (например, открытая строка DataTableToJSON (DataTable))
2) Если ответом на первый вопрос является прежний подход, как лучше всего передать условия ошибки клиенту (запросы JavaScript AJAX, как правило, с помощью jQuery или, в данном конкретном случае, Sencha Touch (Ext))? Мой текущий метод (объясненный ниже в этом вопросе), кажется, работает довольно хорошо, но есть проблема, которая, кажется, зависит от клиента.
Мой «старый» способ возврата ответов от веб-сервисов состоял в том, чтобы объявить все методы как строки. Я занимаюсь этим уже пару лет, и он отлично работает, но чувствует себя немного неуклюже. Например:
public string Test(){
try{
Dataset ds = SomeMethodThatReturnsADataSet();
} catch (Exception ex){
return "ERROR";
//my JS checks for these messages to be sure everything went OK on the server
}
return DataTable_To_JSON(ds);
//at the client this looks something like {d:"[[\"Row1Data\"],[\"Row2Data\"]]"}
}
Очевидно, это создает небольшие накладные расходы на клиенте, потому что у нас должна быть дополнительная строка JavaScript, такая как var data = JSON.parse(response.d);
Так что недавно мне стало известно, что при наличии аргумента ResponseFormat = ResponseFormat.Json
в веб-сервисе .NET будет обрабатывать JSON-кодирование некоторых объектов .NET (к сожалению, я не могу заставить работать тип DataTable, но это другой вопрос). Так что теперь мои методы веб-сервиса выглядят так:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
public List<MyObject> GetMyObjectList(string arg){
List<MyObject> li = MyObjectClass.GetList(arg);
if(li.Count > 500){
//Since we must return a .NET List<MyObject> I can't return strings on error conditions, so this isn't an option:
return "TOO_MANY_RESULTS";
//I saw an example somewhere to do this which works _almost_ great:
throw new Exception("TOO_MANY_RESULTS");
}
return li;
}
Как я уже говорил в комментариях к коду, создание исключения возвращает HTTP 500 с красиво отформатированным ответом JSON, который легко отлавливать и обрабатывать в случае сбоя в обратном вызове Ext.Ajax.request, например так: (используя Chrome и Safari)
{"Message":"TOO_MANY_RESULTS","StackTrace":" at ...","ExceptionType":"System.Exception"}
ОДНАКО, по какой-то причине при тестировании приложения на iPad я получаю «общее» сообщение об исключении:
{"Message":"There was an error processing the request","StackTrace":"","ExceptionType":""}
Я отладил и проследил код, и он действительно попал в ту же строку «выбросить новое исключение» в C #, он не дает сбоя в какой-то другой части кода. По какой-то причине кажется, что заголовки запросов клиента каким-то образом влияют на то, что .NET решает вернуть.
У кого-нибудь есть идеи, как заставить .NET всегда возвращать сообщение, которое я передаю в Исключение?
EDIT : также работает правильно на Android (в ответе сервера получите «TOO_MANY_RESULTS»). Буду тестировать iPhone, как только у меня появится шанс.
РЕДАКТИРОВАТЬ 2 : работает правильно на симуляторе iPhone, физический iPhone сегодня не ладит с нашей беспроводной точкой, не может протестировать реальное устройство.