Вопрос по wcf, svcutil.exe – используйте svcutil для сопоставления нескольких пространств имен для генерации прокси сервисов wcf

12

Я хочу использовать svcutil для сопоставления нескольких пространств имен wsdl с пространством имен clr при создании прокси служб. Я использую строгое управление версиями пространств имен, и, следовательно, сгенерированные пространства имен clr неудобны и могут означать, что многие изменения на стороне клиента будут изменены при изменении версии пространства имен wsdl / xsd. Пример кода будет лучше показать, что я хочу.

// Service code
namespace TestService.StoreService
{
    [DataContract(Namespace = "http://mydomain.com/xsd/Model/Store/2009/07/01")]
    public class Address
    {
        [DataMember(IsRequired = true, Order = 0)]
        public string street { get; set; }
    }

    [ServiceContract(Namespace = "http://mydomain.com/wsdl/StoreService-v1.0")]
    public interface IStoreService
    {
        [OperationContract]
        List<Customer> GetAllCustomersForStore(int storeId);

        [OperationContract]
        Address GetStoreAddress(int storeId);
    }

    public class StoreService : IStoreService
    {
        public List<Customer> GetAllCustomersForStore(int storeId)
        {
            throw new NotImplementedException();
        }

        public Address GetStoreAddress(int storeId)
        {
            throw new NotImplementedException();
        }
    }
}

namespace TestService.CustomerService
{
    [DataContract(Namespace = "http://mydomain.com/xsd/Model/Customer/2009/07/01")]
    public class Address
    {
        [DataMember(IsRequired = true, Order = 0)]
        public string city { get; set; }
    }

    [ServiceContract(Namespace = "http://mydomain.com/wsdl/CustomerService-v1.0")]
    public interface ICustomerService
    {
        [OperationContract]
        Customer GetCustomer(int customerId);

        [OperationContract]
        Address GetStoreAddress(int customerId);
    }

    public class CustomerService : ICustomerService
    {
        public Customer GetCustomer(int customerId)
        {
            throw new NotImplementedException();
        }

        public Address GetStoreAddress(int customerId)
        {
            throw new NotImplementedException();
        }
    }
}

namespace TestService.Shared
{
    [DataContract(Namespace = "http://mydomain.com/xsd/Model/Shared/2009/07/01")]
    public class Customer
    {
        [DataMember(IsRequired = true, Order = 0)]
        public int CustomerId { get; set; }
        [DataMember(IsRequired = true, Order = 1)]
        public string FirstName { get; set; }
    }
}

1. svcutil - without namespace mapping

svcutil.exe /t:metadata 
    TestSvcUtil\bin\debug\TestService.CustomerService.dll     
    TestSvcUtil\bin\debug\TestService.StoreService.dll

svcutil.exe /t:code *.wsdl *.xsd /o:TestClient\WebServiceProxy.cs

Сгенерированный прокси выглядит так

namespace mydomain.com.xsd.Model.Shared._2009._07._011
{
    public partial class Customer{}
}
namespace mydomain.com.xsd.Model.Customer._2009._07._011
{
    public partial class Address{}
}
namespace mydomain.com.xsd.Model.Store._2009._07._011
{
    public partial class Address{}
}

Клиентские классы находятся вне каких-либо пространств имен. Любое изменение в пространстве имен xsd подразумевает изменение всех операторов using в моем клиентском коде, и вся сборка будет нарушена.

2. svcutil - with wildcard namespace mapping

svcutil.exe /t:metadata 
    TestSvcUtil\bin\debug\TestService.CustomerService.dll 
    TestSvcUtil\bin\debug\TestService.StoreService.dll

svcutil.exe /t:code *.wsdl *.xsd /n:*,MyDomain.ServiceProxy 
    /o:TestClient\WebServicesProxy2.cs

Сгенерированный прокси выглядит так

namespace MyDomain.ServiceProxy
{
    public partial class Customer{}
    public partial class Address{}
    public partial class Address1{}
    public partial class CustomerServiceClient{}
    public partial class StoreServiceClient{}
}

Обратите внимание, что svcutil автоматически изменил один из классов Address на Address1. Мне это не нравится. Все клиентские классы также находятся в одном и том же пространстве имен.

What I want

Что-то вроде этого:

svcutil.exe 
    /t:code *.wsdl *.xsd 
    /n:"http://mydomain.com/xsd/Model/Shared/2009/07/01, MyDomain.Model.Shared;http://mydomain.com/xsd/Model/Customer/2009/07/01, MyDomain.Model.Customer;http://mydomain.com/wsdl/CustomerService-v1.0, MyDomain.CustomerServiceProxy;http://mydomain.com/xsd/Model/Store/2009/07/01, MyDomain.Model.Store;http://mydomain.com/wsdl/StoreService-v1.0, MyDomain.StoreServiceProxy" 
    /o:TestClient\WebServiceProxy3.cs

Таким образом, я могу логически сгруппировать пространство имен clr, и любое изменение пространства имен wsdl / xsd будет обрабатываться только при генерации прокси, не затрагивая остальную часть кода на стороне клиента.

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

Я могу сделать одно отображение, как показано ниже, но не несколько

svcutil.exe 
    /t:code *.wsdl *.xsd 
    /n:"http://mydomain.com/xsd/Model/Store/2009/07/01, MyDomain.Model.Address" 
    /o:TestClient\WebServiceProxy4.cs

Но есть ли решение? Svcutil не волшебство, он написан на .Net и программно генерирует прокси. Кто-нибудь написал альтернативу svcutil или указал мне указания, чтобы я мог написать один.

Что произойдет, если вы просто воспользуетесь «Добавить ссылку на сервис»? John Saunders
Я не пробовал, так как мне нужно использовать svcutil для генерации прокси из dll. Но я думаю, учитывая, что «добавить ссылку на службу» имеет возможность ввести только одно пространство имен, это будет то же самое, что и отображение пространства имен с подстановочными знаками. softveda

Ваш Ответ

2   ответа
20

предоставляя дополнительные параметры пространства имен, а не разделяя их точкой с запятой. Таким образом, ваш пример должен быть

svcutil.exe /t:code *.wsdl *.xsd 
/n:http://mydomain.com/xsd/Model/Shared/2009/07/01,MyDomain.Model.Shared 
/n:http://mydomain.com/xsd/Model/Customer/2009/07/01,MyDomain.Model.Customer
/n:http://mydomain.com/wsdl/CustomerService-v1.0,MyDomain.CustomerServiceProxy 
/n:http://mydomain.com/xsd/Model/Store/2009/07/01,MyDomain.Model.Store 
/n:http://mydomain.com/wsdl/StoreService-v1.0,MyDomain.StoreServiceProxy
/o:TestClient\WebServiceProxy3.cs

Хотя в настоящее время у меня возникают проблемы, когда типы, сгенерированные из файлов .xsd, не затрагиваются этими пространствами имен. Только типы, сгенерированные из файлов .wsdl. Документация подразумевает, что оба должны быть.

Я сталкиваюсь с этой проблемой только при использовании коммутатора / сериализатора: XmlSerializer. Для DataContractSerializer типы в основном включены в указанные пространства имен. Согласно этомуотве XmlSerializer не поддерживает эту функцию. Alexander
Не повезло, что отображение пространства имен влияет и на типы xsd? Adi Lester
@ Lester: Я не стал заниматься этим дальше. Мы решили избежать необходимости использования xsds, внедрив эти типы в wsdls, как мне кажется. (Прошло 3 года, заметьте.) Может VS2010 улучшил эту ситуацию? Выше было сделано с VS2008. Dave Cameron
@ DaveCameron Проходит еще пара лет, и я все еще решаю эту проблему в VS2013: - Ian Nelson
1

если вы хотите отобразить все пространства имен схемы в одно пространство имен CLR, тогда:

SvcUtil "your wsdl file.xml" /n:*,RequiredClrNamespace

Похожие вопросы