Как заставить мое клиентское приложение распознавать объект из моего веб-сервиса как тип, который ему уже известен?

Итак, у меня есть веб-сервис, который возвращает пользовательский тип

public List<MyNS.Product> GetProducts(string filter)
{
    ...
}

MyNS.Product определяется в другой сборке. Мое клиентское приложение ссылается на ту же сборку. Когда я добавляю ссылку на службу в свое клиентское приложение, возвращаемый тип — MyServiceReference.Product.

var client = new MyServiceReference.dataSoapClient();
var products = client.GetProducts("derp");
// products type is MyServiceReference.Product[]

Как заставить клиентское приложение распознавать, что возвращенный объект типа MyServiceReference.Product на самом деле является типом MyNS.Product, о котором оно уже знает? (список в часть массива не имеет большого значения, просто тип T)

Веб-сервис — это обычный asmx как часть веб-сайта. Я делаю «добавить ссылку на службу», чтобы добавить службу в мой клиентский проект в Visual Studio.

edit: вот параметры кнопки «Дополнительно» в диалоговом окне добавления ссылки на службу. Я изменил тип коллекции с массива на список. Я также пытался специально выбрать свою библиотеку с типом продукта, но это тоже не помогло.

добавить параметры ссылки на службу


person lincolnk    schedule 21.05.2012    source источник
comment
Если и сервер, и клиент ссылаются на одну и ту же сборку, как можно получить два разных типа?   -  person zmbq    schedule 22.05.2012
comment
Так же, как я написал в своем ответе. Повторное использование dll - это функция WCF. Он не будет работать из коробки с сервисом asmx. Я только что проверил это.   -  person Grzegorz W    schedule 22.05.2012


Ответы (5)


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

Когда вы добавляете веб-ссылку, среда IDE автоматически создает класс, соответствующий интерфейсу веб-службы, на основе определения, возвращенного через SOAP. Поэтому, если вы используете сложный тип, такой как Product, он автоматически сгенерирует собственный класс Product с такими же общедоступными свойствами.

person Steven Doggart    schedule 21.05.2012
comment
Не совсем так. Если у вас есть доступная бизнес-библиотека, вы можете указать VS повторно использовать типы из нее, а не сервисные прокси. - person Val Bakhtin; 22.05.2012
comment
@ValBakhtin Это опция, добавленная в более поздние версии Visual Studio? Я знал, что это вариант для WCF, но я никогда не пользовался веб-сервисами до своей новой работы, где они вынуждают нас использовать VS2005 по какой-то нелепой неизвестной причине. - person Steven Doggart; 22.05.2012
comment
Я знаю, что это было в 2008 и 2010 годах. Щелкните правой кнопкой мыши ссылку на службу и выберите пункт меню «Настроить ссылку на службу». - person Val Bakhtin; 22.05.2012
comment
Абсолютно, только что протестировал его для VS 2010, когда вы добавляете новую ссылку, нажмите кнопку «Дополнительно». - person Val Bakhtin; 22.05.2012
comment
@ValBakhtin Но есть такие ссылки, как эта infiniteimprobability.blogspot.com /2009/02/ (по общему признанию, старый), в котором говорится, что опция есть, но не влияет на веб-сервисы. Может быть, это было что-то новое в 2010 году. - person Steven Doggart; 22.05.2012
comment
хорошо, может быть. Прошло некоторое время с тех пор, как я использовал чистые веб-сервисы. - person Val Bakhtin; 22.05.2012

Когда вы добавляете ссылку на сервис, скажите VS повторно использовать объекты из вашей бизнес-библиотеки. И пока ваш сервис и клиент используют одну и ту же версию бизнес-библиотеки, Visual Studio будет выбирать правильные типы вместо сервисных прокси.

person Val Bakhtin    schedule 21.05.2012
comment
Я нашел флажок повторного использования в дополнительных параметрах, но он всегда установлен. Я делаю что-то еще не так? - person lincolnk; 22.05.2012
comment
Проблема может возникнуть, если у вас не совпадают версии dll и типы имеют разные подписи, или один из проектов ссылается на старую версию библиотеки. Проверьте свои версии dll после создания решения, если dll одинаковы с обеих сторон. - person Val Bakhtin; 22.05.2012
comment
Проблема возникает из-за того, что это веб-служба ASMX. Не WCF. - person Grzegorz W; 22.05.2012

Поскольку вы используете мыло (.asmx создает веб-службу SOAP), клиент должен иметь возможность извлекать ввод со страницы wsdl мыла, которую создает ваш asmx, вам просто нужно убедиться, что передаваемый вами объект является сериализуемым в xml.

Как правило, я создам dto (объект передачи данных) для хранения данных, переданных клиенту, чтобы убедиться, что они сериализуемы, и отделить их от остальной части моего приложения, чтобы предотвратить проблемы, вызванные обновлением существующий объект.

Это также работает с клиентами, отличными от .NET, например, вы можете использовать вызов SOAP из .NET в java таким же образом.

person Bob The Janitor    schedule 21.05.2012

Общие типы — это функция, представленная в WCF, но не в старых веб-службах asmx. Для старого ASMX попробуйте SchemaImporterExtension: ссылка

Изменить: ОК. Итак, я проверил, и это можно сделать, вручную создав сервисный контракт, классы запросов и ответов и вручную создав канал. Вам нужно установить [XmlSerializerFormat] в вашем контракте и убедиться, что ваш объект имеет [SerializableAttribute]

person Grzegorz W    schedule 21.05.2012

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

ПРОЛОГ

Я использую веб-службу asmx (.net версии 2.0), и у меня есть веб-метод, который возвращает настраиваемый тип (с атрибутом [serializable]), на который ссылается сборка, в которой оба проекта (фактически веб-служба и клиент) Поделиться.

Решение, которое я нашел, состоит в том, чтобы позволить Visual Studio создать для вас клиент (в клиентском проекте), а затем изменить созданный файл Reference.cs (чтобы увидеть его, вам нужно включить «показать все файлы»).

Примечание. Версия клиентского проекта .NET также должна быть 2.0.

НО ОСТЕРЕГАЙТЕСЬ!!

поскольку это автоматически сгенерированный файл, если вы обновите ссылку на веб-сервис, все изменения БУДУТ ПОТЕРЯНЫ! так что обратите МНОГО внимания.

Как вы можете видеть в этом файле (reference.cs), пользовательский тип воссоздается со всеми свойствами и, если класс наследуется от другого (как в моем случае), также воссоздается базовый класс. Очевидно, проблема в том, что воссозданные типы НЕ совпадают с общими сборками.

Решение, которое я нашел, состоит в том, чтобы переименовать сгенерированные классы (например, поставить «_» перед именами [YOUR_BASECLASS_NAME => _YOUR_BASECLASS_NAME]), а затем в «использующей» части Reference.cs поместить что-то вроде этого:

using YOUR_BASECLASS_NAME = SHAREDLIBRARY.BASECLASS
using YOUR_CLASS_NAME = SHAREDLIBRARY.CLASS

сделайте это для всех классов, которые вы используете.

Скомпилируйте... и вуаля! я знаю, что это не очень хорошее решение, но это самое умное, что я нашел.

person kindaska    schedule 06.08.2015