wcf посилання не генерується правильно

Пройшла дивна проблема з моїми посиланнями на WCF цього ранку. У двох словах, я встановлюю дуплексний сервіс, щоб сервер міг повідомити клієнта, відправивши об'єкти в контракт з даними. Коли клієнт з'єднується, він запускає функцію на сервері, щоб повернути List (Of NewItem) на основі того, що знаходиться в загальній черзі класу обслуговування. Проблема полягає в тому, що, коли я оновлюю посилання в службі клієнта, він говорить, що функція повертає об'єкт NewItem , а не об'єкт List (Of NewItem) . Я можу перейти в довідник і вручну змінити його на об'єкт List , і він буде переданий тільки добре. Будь-які ідеї, чому сервісний еталонний генератор довільно змінить тип повернення?

Ось відповідний код:


Public Interface INotifyService
    
    Function GetNewServerItems() As List(Of NewItem)
End Interface



Public Class NewItem
    
    Public Property ItemNum As String

    
    Public Property Timestamp As DateTime
End Class


Public Class NotifyService
    Implements INotifyService

    Shared _server_items As New List(Of NewItem)

    Public Function GetNewServerItems() As List(Of NewItem)
        Return _server_items
    End Function
End Class

А в Reference.vb (спрощений):

  _
Function GetNewServerItems() As NotifyGateway.NewItem()
1
@Gabobcat - так.
додано Автор mounty, джерело
@ Джон Сондерс - не випадково. Я залишив їх, тому що це довгий контракт, і я хотів включити лише голі кістки. Я додав їх.
додано Автор mounty, джерело
Ви випадково випустили ?
додано Автор John Saunders, джерело
Невелике, але важливе роз'яснення до оригінального повідомлення: функція повертає масив об'єктів NewItem, а не жодного об'єкта NewItem. Ви можете легко створити список (з NewItem) на стороні, що приймає, і завантажити його з масиву або просто використовувати масив як-есть, якщо зміна типового типу колекції викликає інші побічні ефекти.
додано Автор competent_tech, джерело
Ви додали свою реферат, клацнувши правою кнопкою миші на вашому проекті та вибравши "Додати службову довідку"?
додано Автор Gabe Thorns, джерело

3 Відповіді

Ви і я потрапили в ту саму ловушку: ми обидва неправильно читаємо код VB.NET, створений для проксі-методу, як повернення одного елемента. По суті, це повертає масив.

WSDL використовує схему xml для опису форми запиту та відповіді. xml схема не має поняття "список", тільки послідовності. За замовчуванням, коли він бачить послідовність елементів, "Add Service Reference" генерує масив. Ви можете змінити це, щоб створити "Список", просто змінюючи тип колекції на вкладці "Додатково" в діалогових вікнах "Додати службовий довідник" або "Налаштувати довідку служби".

3
додано
...ти правий. NewItem не є таким самим, як NewItem() . Слід це зауважити.
додано Автор mounty, джерело

Існує ще один менш відомий, але більш потужний механізм збереження типів збірки, не вдаючись до використання параметра типового типу колекції.

Цей механізм особливо корисний, якщо у вас є ClassDataContract класів, які ви використовуєте у своєму коді на обох сторонах труби WCF.

Рішення передбачає редагування svcmap, яке створюється як частина посилання служби WCF, і додаванням певних записів CollectionMapping для кожного з типів збірки, який ви хочете серіалізувати. Перш за все слід звернути увагу на унікальні форми: якщо WCF знаходить більше одного відповідності для даного класу, він відмовиться генерувати код.

Щоб внести зміни:

1) Показати всі файли в проекті, що містять посилання на службу WCF.

2) Розширити посилання на послуги

3) Двічі клацніть файл Reference.svmap, щоб редагувати його.

4) Додайте записи в розділ CollectionMappings (якщо його не існує, ви можете додати його).

Наприклад, для того, щоб передати загальні словники та списки, а для передачі StringCollections, ви можете мати такі записи:


  
  
  

Перший елемент із категорією «Словник» буде служити типовим набором словника за замовчуванням, і перший елемент із категорією «Список» буде служити типовим назвою колекції.

У нас є більше 200 класів збору, які ми використовуємо таким чином для клієнтів Silverlight та Windows Forms, і це надзвичайно ефективний спосіб повторно використовувати ваш власний код з обох сторін труби WCF.

Одне важливе зауваження: щоб повторно використовувати ваші класи, вам слід переконатися, що прапорець "Повторне використання типів у посиланнях збірки" в конфігурації посилання служби перевіряється або той, що прапорець GenerateInternalTypes у reference.svmap встановлено на "false" (вони однакові річ)

1
додано

При додаванні посилання, як ви це зробили, слід змінити тип "Тип збірки" у параметрах додаткової служби Reference (Додати службовий діалог) до "system.Collections.Generic.List". За замовчуванням це "System.Array".

Я б не рекомендував хоча, використовуючи посилання «Додати посилання», оскільки ви втрачаєте контроль над конфігурацією служби WCF, а VS додає багато сміття, які вам не потрібні, і це ускладнить підтримку вашої клієнтської/службової зв'язки.

Сподіваюся, це допоможе.

1
додано
Перша частина відповіді, здається, вирішує негайну проблему. Що стосується другої частини відповіді: яким чином я додам посилання на послугу або іншим способом отримає свій контракт на роботу, не використовуючи метод «Додати службовий довідник»? (І так, я використовую .NET 4.)
додано Автор mounty, джерело
-1: Будь ласка, не робіть таких рекомендацій без додаткового обґрунтування. Також, не питаючи, яка версія .NET використовується, оскільки .NET 4.0 видає набагато менший файл конфігурації, видаливши значення за замовчуванням.
додано Автор John Saunders, джерело
Поправді, вибачте про це. Я не мав на увазі файл конфігурації, я мав на увазі, що при використанні "Додати службову довідку" результат є неймовірно багатослівним, складним для керування та підтримки, зміна конфігурації може бути переписана, замість повторного використання вашого інтерфейсу він генерує дублікат. Таким чином, IMHO, вручну налаштувати WCF (вручну або за допомогою відповідного інструмента), є найкращим способом перейти, і я повинен був так висловити це раніше. Сподіваюся, це зробить мою відповідь яскравішою, і ще раз шкода.
додано Автор Gabe Thorns, джерело
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug