Подтвердить что ты не робот

Пространство имен ссылок службы WCF отличается от исходного

У меня проблема с пространствами имен, используемыми моими ссылками на службы. У меня есть несколько служб WCF, скажем, с пространством имен MyCompany.Services.MyProduct (фактическое пространство имен больше).
Как часть продукта, я также предоставляю образец веб-сайта С#.NET. Это веб-приложение использует пространство имен MyCompany.MyProduct.

Во время первоначальной разработки служба была добавлена ​​как ссылка на проект на веб-сайт и используется напрямую. Я использовал шаблон factory, который возвращает экземпляр объекта, который реализует MyCompany.Services.MyProduct.IMyService. Пока что так хорошо.

Теперь я хочу изменить это, чтобы использовать фактическую ссылку на службу. После добавления ссылки и ввода MyCompany.Services.MyProduct в текстовое поле пространства имен он генерирует классы в пространстве имен MyCompany.MyProduct.MyCompany.Services.MyProduct. ПЛОХО! Я не хочу менять директивы using в нескольких местах только потому, что я использую прокси-класс. Поэтому я попробовал добавить пространство имен с global::, но это не принято.

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

Единственное решение, с которым я столкнулся, - это установить пространство имен по умолчанию для моего веб-приложения на MyCompany (потому что оно не может быть пустым) и добавление служебной ссылки как Services.MyProduct. Предположим, что клиент хочет использовать мой образец веб-сайта в качестве отправной точки, и они меняют пространство имен по умолчанию на OtherCompany.Whatever, это, очевидно, нарушит мое обходное решение.

Есть ли хорошее решение этой проблемы?

Подводя итог: я хочу создать служебный прокси-сервер службы в исходном пространстве имен, не ссылаясь на сборку.

Примечание: я видел этот вопрос, но не было решения, которое было бы приемлемым для моего варианта использования.


Изменить: Как предложил Джон Сондерс, я представил некоторые отзывы в Microsoft об этом:
Элемент обратной связи @Microsoft Connect

4b9b3361

Ответ 1

Я добавил в свой блог запись этого решения. Такая же информация действительно, но, возможно, немного менее фрагментированная

Я нашел альтернативу использованию svcutil.exe для выполнения того, что я хочу. Он (imo) упрощает обновление служебной ссылки, чем перезапуск утилиты.

Вы должны явно указать uri пространства имен в своих ServiceContract и DataContracts (см. ниже для комментариев).

[ServiceContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public interface IService
{
    [OperationContract]
    CompositeType GetData();
}

[DataContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public class CompositeType
{
    // Whatever
}

Пространство имен может быть любым, но технически оно должно быть действительным uri, поэтому я выбрал эту схему. Возможно, вам придется вручную создавать вещи для работы, поэтому сделайте это.

Как только это будет сделано, включите параметр Показать все файлы в обозревателе решений. Разверните ссылку на службу, добавленную ранее. Дважды щелкните файл Reference.svcmap.

Будет элемент <NamespaceMappings />, который вам нужно будет отредактировать. Продолжая мой пример:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="http://company.com/MyCompany.Services.MyProduct"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

Сохраните файл, щелкните правой кнопкой мыши ссылку на службу и выберите Обновить ссылку службы.

Вы можете добавить столько отображений, сколько вам нужно (мне действительно нужны были два). Эффект такой же, как подход svcutil /namespace:, но без использования самой командной строки, что упрощает его обновление.

Разница с svcutil

Недостатком этого подхода является то, что вам нужно использовать явные сопоставления пространства имен. Используя svcutil, у вас есть возможность сопоставить все, явно не отображаемые таким образом (решение, на которое ссылался Джон Сондерс):

svcutil /namespace:*,MyCompany.Services.MyProduct ...

Возможно, вы подумали использовать:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="*"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

но это будет не, потому что Visual Studio уже неявно добавляет это сопоставление, указывая на сгенерированное имя пространства имен, от которого мы пытаемся избавиться. Вышеупомянутая конфигурация заставит Visual Studio жаловаться на дублирующий ключ.

Явное пространство имен объявлений:
Если в вашем коде не указано пространство имен эксплимента, кажется, что .NET будет генерировать uri формы http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct. Вы можете сопоставить это как и явные пространства имен в моем примере, но я не знаю, есть ли какие-либо гарантии для этого поведения. Следовательно, переход с явным пространством имен может быть лучше.

NB: отображение двух пространств имен TargetNames в одно и то же пространство ClrNamespace приводит к нарушению генерации кода

Ответ 2

Ваш случай использования был неправильным.

Вы никогда не должны были включать службу в качестве ссылки в первую очередь.

Я считаю, что svcutil.exe примет переключатель, определяющий полное пространство имен, которое будет использоваться.

Ответ 3

В VS2010 и более поздних версиях существует способ настройки пользовательских пространств имен. В проводнике решений выберите "Показать все файлы", затем откройте "Веб-ссылки" в дереве решений, выберите службу, выберите Reference.map node, покажите свойства и установите Свойство пространства имен пользовательского инструмента.

К сожалению, у меня недостаточно репутации, чтобы показать скриншот.