Pytanie w sprawie wcf, svcutil.exe – użyj svcutil do mapowania wielu przestrzeni nazw w celu wygenerowania proxy usługi wcf

12

Chcę użyć svcutil do mapowania wielu przestrzeni nazw wsdl na przestrzeń nazw clr podczas generowania serwerów proxy usług. Używam silnego wersjonowania przestrzeni nazw, dlatego wygenerowane przestrzenie nazw clr są niewygodne i mogą oznaczać, że wiele zmian kodu po stronie klienta ulega zmianie, jeśli zmieni się wersja przestrzeni nazw wsdl / xsd. Przykład kodu lepiej pokazać, co chcę.

// 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 - bez mapowania przestrzeni nazw

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

Wygenerowany proxy wygląda

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{}
}

Klasy klientów nie mają żadnych przestrzeni nazw. Każda zmiana w przestrzeni nazw xsd oznaczałaby zmianę wszystkich przy użyciu instrukcji w moim kodzie klienta, wszystkie kompilacje zostaną przerwane.

2. svcutil - z mapowaniem przestrzeni nazw wieloznacznych

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

Wygenerowany proxy wygląda

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

Zauważ, że svcutil automatycznie zmienił jedną z klasy Address na Address1. Nie podoba mi się to. Wszystkie klasy klientów znajdują się również w tej samej przestrzeni nazw.

Czego chcę

Coś takiego:

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

W ten sposób mogę logicznie pogrupować przestrzeń nazw clr i wszelkie zmiany w przestrzeni nazw wsdl / xsd są obsługiwane tylko w generowaniu proxy bez wpływu na resztę kodu po stronie klienta.

Teraz to nie jest możliwe. Svcutil pozwala zamapować tylko jedną lub wszystkie przestrzenie nazw, a nie listę mapowań.

Mogę zrobić jedno mapowanie, jak pokazano poniżej, ale nie wiele

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

Ale czy istnieje jakieś rozwiązanie. Svcutil nie jest magią, jest napisany w .Net i programowo generuje serwery proxy. Czy ktoś napisał alternatywę do svcutil lub wskazał mi kierunki, abym mógł napisać jeden.

Nie próbowałem, ponieważ muszę użyć svcutil do generowania proxy z biblioteki DLL. Ale sądzę, że biorąc pod uwagę, że „dodaj odwołanie do usługi” ma opcję wprowadzania tylko jednej przestrzeni nazw, byłoby to samo, co mapowanie przestrzeni nazw wieloznacznych. softveda
Co się stanie, jeśli po prostu użyjesz polecenia „Dodaj usługę”? John Saunders

Twoja odpowiedź

2   odpowiedź
1

Na wypadek, gdybyś chciał odwzorować wszystkie przestrzenie nazw schematu na jedną przestrzeń nazw CLR, a następnie:

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

Możesz wykonać wiele mapowań przestrzeni nazw, podając dodatkowe parametry przestrzeni nazw - nie przez rozdzielenie ich średnikiem. Twój przykład powinien być zamiast tego

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

Chociaż obecnie mam problemy z tym, że te przestrzenie nazw nie wpływają na typy generowane z plików .xsd. Są tylko typy wygenerowane z plików .wsdl. Dokumentacja sugeruje, że oba powinny być.

Stoję przed tym problemem tylko przy użyciu przełącznika / serializatora: XmlSerializer. Dla DataContractSerializer typy są ściśle uwzględnione w określonych przestrzeniach nazw. Według tegoodpowiedź XmlSerializer nie obsługuje tej funkcji. Alexander
@DaveCameron Minęło kolejne kilka lat i wciąż uderzam w ten sam problem w VS2013 :-( Ian Nelson
@Lester: W tamtym czasie nie prowadziłem tego dalej. Skończyło się na tym, że uniknęliśmy potrzeby korzystania z xsds przez osadzenie tych typów w WSDL. (Minęły 3 lata, pamiętaj.) Może VS2010 poprawiło się w tej sytuacji? Powyższe zostało wykonane za pomocą VS2008. Dave Cameron
Jakieś szczęście, że mapowanie przestrzeni nazw wpłynie również na typy xsd? Adi Lester

Powiązane pytania