Frage an wcf, svcutil.exe – Verwenden Sie svcutil, um mehrere Namespaces für die Generierung von wcf-Service-Proxys zuzuordnen

12

Ich möchte svcutil verwenden, um beim Generieren von Service-Proxys mehrere WSDL-Namespaces dem CLR-Namespace zuzuordnen. Ich verwende eine starke Versionierung von Namespaces und daher sind die generierten clr-Namespaces umständlich und können viele clientseitige Codeänderungen bedeuten, wenn sich die wsdl / xsd-Namespace-Version ändert. Ein Codebeispiel wäre besser, um zu zeigen, was ich will.

// 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 - ohne Namespace-Zuordnung

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

Der generierte Proxy sieht aus wie

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

Die Clientklassen haben keine Namespaces. Jede Änderung am xsd-Namespace würde bedeuten, dass alle using-Anweisungen in meinem Client-Code geändert werden und der gesamte Build abstürzt.

2. svcutil - mit Platzhalter-Namespace-Zuordnung

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

Der generierte Proxy sieht aus wie

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

Beachten Sie, dass svcutil automatisch eine der Adressklassen in Address1 geändert hat. Ich mag das nicht. Alle Client-Klassen befinden sich ebenfalls im selben Namespace.

Was ich möchte

Etwas wie das:

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

Auf diese Weise kann ich den clr-Namespace logisch gruppieren, und jede Änderung des wsdl / xsd-Namespace wird nur in der Proxy-Generierung behandelt, ohne den Rest des clientseitigen Codes zu beeinflussen.

Das ist jetzt nicht möglich. Mit svcutil können Sie nur einen oder alle Namespaces zuordnen, nicht eine Liste von Zuordnungen.

Ich kann eine Zuordnung wie unten gezeigt vornehmen, aber nicht mehrere

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

Aber gibt es eine Lösung. Svcutil ist keine Zauberei, es ist in .Net geschrieben und generiert die Proxys programmgesteuert. Hat jemand eine Alternative zu svcutil geschrieben oder mir Anweisungen gegeben, damit ich eine schreiben kann?

Was passiert, wenn Sie nur "Servicereferenz hinzufügen" verwenden? John Saunders
Ich habe nicht versucht, da ich das svcutil verwenden muss, um Proxy von DLL zu erzeugen. Aber ich denke, da "Dienstreferenz hinzufügen" die Option hat, nur einen Namespace einzugeben, ist dies dasselbe wie die Zuordnung von Platzhalternamespaces. softveda

Deine Antwort

2   die antwort
1

dass Sie alle Schema-Namespaces einem CLR-Namespace zuordnen möchten:

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

indem Sie zusätzliche Namespace-Parameter angeben - nicht durch Semikolon. So sollte Ihr Beispiel stattdessen sein

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

Derzeit habe ich jedoch Probleme, wenn die aus XSD-Dateien generierten Typen von diesen Namespaces nicht betroffen sind. Es werden nur die aus den WSDL-Dateien generierten Typen verwendet. Die Dokumentation impliziert, dass beides sein sollte.

Haben Sie Glück, dass sich die Namespace-Zuordnung auch auf die xsd-Typen auswirkt? Adi Lester
@Lester: Ich habe es damals nicht weiter verfolgt. Wir haben die Notwendigkeit von xsds vermieden, indem wir diese Typen in die wsdls eingebettet haben, denke ich. (Es sind wohlgemerkt 3 Jahre vergangen.) Vielleicht hat VS2010 diese Situation verbessert? Das obige wurde mit VS2008 gemacht. Dave Cameron
@ DaveCameron Noch ein paar Jahre vergehen, und ich stoße immer noch auf dasselbe Problem in VS2013 :-( Ian Nelson
Ich habe dieses Problem nur bei Verwendung des Switches / Serializers: XmlSerializer. Für DataContractSerializer sind die Typen korrekt in den angegebenen Namespaces enthalten. DemzufolgeAntworten XmlSerializer unterstützt diese Funktion nicht. Alexander

Verwandte Fragen