Из того, что я узнал от них, я понял, что это не очень хорошая практика для общения с iPhone (например, отсутствие хороших способов использования WSDL).
Самой большой проблемой является не отсутствие хороших «инструментов», а отсутствие понимания, что такое WSDL и как работают веб-сервисы.Все эти инструменты, генерирующие сервисные заглушки для разработчиков, привели к тому, что разработчики не понимают, что скрывается за ними.Он работает для базовых сценариев, где все волшебство сделано для вас, но как только разработчики должны отслеживать любую проблему или расширять «инструмент» дополнительными функциями, у них возникают большие проблемы (и это обычно приводит к плохому решению).Честно говоря, разработка ПО не связана с базовыми сценариями.
REST ставит перед разработчиками большие проблемы, поскольку они не предоставляют никаких «волшебных» инструментов.REST касается правильного использования протокола HTTP и использует все преимущества существующей инфраструктуры HTTP.Без понимания основ HTTP-протокола вы не сможете создать хороший REST-сервис.Вот где вы должны начать.
Вот пример неправильного использования:
[OperationContract]
[WebGet(UriTemplate = "/login?username={userName}&password={password}&softwareVersion={softwareVersion}", ResponseFormat=WebMessageFormat.Json)]
ITicket Login(string userName, string password, string softwareVersion);
Login
метод, очевидно, выполняет какое-то действие - я думаю, он создает тикет.Это абсолютно не подходит для GET HTTP-запроса.Это определенно должен быть запрос POST к ресурсу Login, возвращающий новое представление ITicket
для каждого вызова.Зачем?Потому что запросы GET должны быть безопасными и идемпотентными.
- Безопасный: запрос не должен вызывать побочных эффектов = он не должен вносить никаких изменений в ресурс, но в вашем случае он, скорее всего, создает новый ресурс.
- Идемпотентность: этодля примера это не так важно, поскольку вы уже нарушили правило Safe, но это означает, что запрос к ресурсу должен повторяться.Это означает, что первый запрос с тем же именем пользователя, паролем и версией может создать новый ресурс, но когда запрос будет выполнен снова, он не должен создавать новый ресурс, а возвращать уже созданный.Это имеет больше смысла, когда ресурс сохраняется / поддерживается на сервере.
Поскольку HTTP-запрос GET инфраструктурой HTTP считается безопасным и идемпотентным, он обрабатывается по-другому.Например, запросы GET могут быть перенаправлены в кеширование и т. Д. Если запрос небезопасен и идемпотентен, он должен использовать метод POST.Поэтому правильное определение:
[OperationContract]
[WebInvoke(UriTemplate = "/login?username={userName}&password={password}&softwareVersion={softwareVersion}", ResponseFormat=WebMessageFormat.Json)]
ITicket Login(string userName, string password, string softwareVersion);
, потому что WebInvoke
по умолчанию использует метод POST.Это также причина, по которой все туннелирование протоколов (например, SOAP) обычно используют HTTP-методы POST для всех запросов.
Другой проблемой в предыдущем примере может быть снова подход REST = полное использование инфраструктуры HTTP.Он должен использовать HTTP-аутентификацию (логин) = Basic, Digest, OAuth и т. Д. Это не означает, что у вас не может быть аналогичного ресурса, но вы должны сначала рассмотреть возможность использования стандартного способа HTTP.
Ваш второй пример на самом деленамного лучше, но у него есть проблемы с ограничением WCF.WCF может читать из URL только основные типы (кстати, как вы хотите передать объект в URL?).Любой другой тип параметра требует специального поведения WCF.Если вам нужно предоставить метод, который принимает контракт данных, вы должны снова использовать метод HTTP, который принимает параметры в теле - снова используйте POST и поместите сериализованный билет JSON в тело запроса:
[OperationContract]
[WebInvoke(UriTemplate = "/GetMetaData",RequestFormat=WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
IMetaData GetMetaData(ITicket ticket);