Служба WCF, возвращающая пользовательский класс, генерирует ошибки в Reference.cs

#c# #visual-studio-2008 #wcf #datacontract

#c# #visual-studio-2008 #wcf #datacontract

Вопрос:

У меня есть проект службы WCF в Visual Studio 2008, который содержит около 12 методов, некоторые из которых возвращают примитивные типы, такие как bool или string. У меня также есть проект модульного тестирования Visual Studio, который ссылается на опубликованную службу WCF. Тестовый проект успешно компилируется, когда все возвращаемые типы являются примитивными.

Если я добавлю новый метод в службу, возвращающую пользовательский класс, опубликую его и обновлю ссылку на службу в тестовом проекте, он не скомпилируется. Ошибки являются: —

  1. Тип ‘PublisherFaultException’ уже содержит определение ‘Reason’.
  2. Тип ‘PublisherFaultException’ уже содержит определение для ‘PropertyChanged’.
  3. Введите ‘Publisher.Test.LibraryReference.PublisherFaultException’ уже определяет элемент с именем ‘RaisePropertyChanged’ с теми же типами параметров.

все в автоматически сгенерированном файле reference.cs.

Контракт для метода службы WCF является: —

 Page GetItem(string path);
  

и класс Page имеет атрибут DataContract, а его общедоступные свойства имеют атрибут DataMember .

Я неохотно изменяю файл Reference.cs, поскольку мне нужно будет делать это каждый раз при обновлении службы.

Кто-нибудь знает, почему это происходит?

Стюарт.

Комментарии:

1. происходит то, что WCF добавляет ссылку на службу, это сука — я чувствую вашу боль

2. Вы пытались сгенерировать прокси с помощью svcutil? Я помню, что у меня была эта проблема раньше, и это было, когда я создавал пользовательские исключения из-за сбоев, используя атрибут FaultContract . Я не помню решение. Надеюсь, мои комментарии могли бы помочь. Я продолжу копать и посмотрю, смогу ли я найти решение. Попробуйте SvcUtil.exe и посмотрите, что происходит, и дайте нам знать.

Ответ №1:

Когда вы добавляете ссылку на службу, вы получаете опцию «повторно использовать типы в сборке» — вероятно, это ключ к устранению дублирования.

Или у вас есть какие-то тестовые ссылки, которые вызывают дублирование?

Кроме того, загляните в раздел References дерева проекта и посмотрите, нет ли там чего-нибудь неожиданного (есть ли у вас ссылки на 2 сборки, которые содержат ссылки на службы в одном пространстве имен?).

Комментарии:

1. Выбран параметр «Типы повторного использования во всех ссылочных сборках». Должно ли это быть так? Класс Page принадлежит сборке, на которую, хотя она и находится в решении VS, тестовый проект не ссылается напрямую.

2. Повторное использование, как правило, работает хорошо, хотя есть [многословные] аргументы в пользу отказа от контракта на совместное использование таким образом. Есть ли исключение PublisherFaultException в сборке contracts? Помечен ли он соответствующими атрибутами контракта? (Я не видел точного случая, который вы видите, но я был бы корнем, вызывающим это, следуя по цепочке ссылок). Я так понимаю, вы нажали на кнопку показать все файлы в верхней части project explorer и заглянули в references.cs, чтобы увидеть сгенерированный код, чтобы определить, с чем он может конфликтовать?

3. Исключение PublisherFaultexception находится в автоматически сгенерированном файле Reference.cs при обновлении ссылки на службу. Она содержит два объявления класса для PublisherFaultException (оба частичных класса, что нормально), но оба с общедоступным свойством Reason, событием PropertyChanged и методом RaisePropertyChanged . Сам класс ReportPublisherException находится в проекте WCF и имеет атрибуты DataContact и DataMember.

4. Тогда, похоже, проблема в том, что «обнаружение общего доступа» не улавливает тот факт, что он «уже есть». Отсюда мое последнее предположение о том, что в вашем классе ошибок отсутствует атрибут Contract. Думаю, это [FaultContract]…

Ответ №2:

Использование автоматически сгенерированного прокси-класса всегда сопряжено с трудностями.

Чтобы справиться с подобной ситуацией, я использую отдельную сборку с классами контрактов данных и интерфейсом сервиса.

Контрактная dll будет иметь:

 
public interface IService
{
    [OperationContract]
    List GetContentList();
}

[DataContract]
public class ContentItem
{
  [DataMember] public string Name;
  [DataMember] public object Data;
}
  

У клиента будет ссылка на Contract.dll .
Прокси-сервер будет создан вручную:

 
class ServiceProxy : ClientBase<IService>, IService
 {
  public List GetContentList()
  {
   return Channel.GetContentList();
  }
 }

  

Серверная библиотека dll будет иметь ссылку на ту же самую библиотеку dll контракта.
Таким образом, мы сможем избежать любых ошибок с автоматически сгенерированным прокси.
Кроме того, созданный вручную прокси-сервер будет более простым и управляемым.

Ответ №3:

При добавлении ссылки на службу попробуйте нажать Дополнительно и выберите «Генерировать асинхронные операции».

Я думаю, что происходило то, что в веб-службе были некоторые асинхронные методы с именами, заканчивающимися на «Async», которые конфликтовали бы с методами, сгенерированными в References.cs.

например, представьте, что веб-служба содержит 2 метода: (1) SayHello и (2) SayHelloAsync .

Генерация с использованием метода на основе задач по умолчанию приводит к:

  • SayHello и SayHelloAsync для (1)
  • SayHelloAsync и SayHelloAsyncAsync для (2).

Конфликт произошел из-за того, что было вызвано 2 сгенерированных метода SayHelloAsync .

По крайней мере, я думаю, что это то, что происходило. В любом случае, настройка «Генерировать асинхронные операции» сработала для меня.