#c# #visual-studio-2008 #wcf #datacontract
#c# #visual-studio-2008 #wcf #datacontract
Вопрос:
У меня есть проект службы WCF в Visual Studio 2008, который содержит около 12 методов, некоторые из которых возвращают примитивные типы, такие как bool или string. У меня также есть проект модульного тестирования Visual Studio, который ссылается на опубликованную службу WCF. Тестовый проект успешно компилируется, когда все возвращаемые типы являются примитивными.
Если я добавлю новый метод в службу, возвращающую пользовательский класс, опубликую его и обновлю ссылку на службу в тестовом проекте, он не скомпилируется. Ошибки являются: —
- Тип ‘PublisherFaultException’ уже содержит определение ‘Reason’.
- Тип ‘PublisherFaultException’ уже содержит определение для ‘PropertyChanged’.
- Введите ‘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
.
По крайней мере, я думаю, что это то, что происходило. В любом случае, настройка «Генерировать асинхронные операции» сработала для меня.