使用svcutil映射多个名称空间以生成wcf服务代理

使用svcutil映射多个名称空间以生成wcf服务代理,wcf,svcutil.exe,Wcf,Svcutil.exe,我想在生成服务代理时使用svcutil将多个wsdl命名空间映射到clr命名空间。我使用名称空间的强版本控制,因此生成的clr名称空间很笨拙,如果wsdl/xsd名称空间版本发生更改,可能意味着许多客户端代码发生更改。一个代码示例可以更好地显示我想要的内容 // Service code namespace TestService.StoreService { [DataContract(Namespace = "http://mydomain.com/xsd/Model/Store/2

我想在生成服务代理时使用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; }
    }
}
生成的代理看起来像

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{}
}
namespace MyDomain.ServiceProxy
{
    public partial class Customer{}
    public partial class Address{}
    public partial class Address1{}
    public partial class CustomerServiceClient{}
    public partial class StoreServiceClient{}
}
客户端类已超出任何名称空间。对xsd名称空间的任何更改都意味着更改客户机代码中的所有using语句,所有构建都将中断

2。svcutil-具有通配符命名空间映射

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
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.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{}
}
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。我不喜欢这个。所有客户机类也位于同一命名空间内

我想要什么

大概是这样的:

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的替代项,或者为我指明了方向,以便我可以编写一个。

您可以通过提供其他名称空间参数(而不是通过分号分隔它们)来进行多个名称空间映射。所以你的例子应该是

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文件生成的类型。文档暗示这两者都应该是。

以防您希望将所有架构名称空间映射到一个CLR名称空间,然后:

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

如果只使用“添加服务引用”,会发生什么?我没有尝试过,因为我需要使用svcutil从dll生成代理。但是我想,如果“添加服务引用”可以选择只输入一个名称空间,那么它将与通配符名称空间映射相同。名称空间映射也会影响xsd类型吗?@Lester:我当时没有进一步研究它。我认为,通过将这些类型嵌入到wsdl中,我们最终避免了对xsd的需要。(请注意,已经三年了。)也许VS2010改善了这种情况?上述内容是在VS2008中完成的。@DaveCameron又过了几年,我仍然在VS2013中提到同样的问题:-(只有在使用开关/序列化程序时,我才面临此问题:XmlSerializer。对于DataContractSerializer,类型正确地包含在指定的命名空间中。根据此XmlSerializer,它不支持此功能。