C# 不使用XSD共享WSDL类型

C# 不使用XSD共享WSDL类型,c#,wcf,web-services,xsd,wsdl,C#,Wcf,Web Services,Xsd,Wsdl,我似乎找不到一个示例,可以从共享类型的wsdl生成代理,但不附带任何xsd。谁能把这个标记为重复的并给我举个例子吗 这里有两个服务,每个服务都有自己的名称空间和一个公共类型。唯一可以公开访问的是它们的wsdl,没有类型的XSD或其.dll可以传递到wsdl.exe/sharedtypes或svcutils,没有它,我就得到了相同的class Foo,无法传递到SetFoo和class Foo1 我能想到的最好办法是通过编程方式生成代理并通过CodeDOM检测重复项,忽略DataContract/

我似乎找不到一个示例,可以从共享类型的wsdl生成代理,但不附带任何xsd。谁能把这个标记为重复的并给我举个例子吗

这里有两个服务,每个服务都有自己的名称空间和一个公共类型。唯一可以公开访问的是它们的wsdl,没有类型的XSD或其.dll可以传递到
wsdl.exe/sharedtypes
svcutils
,没有它,我就得到了相同的
class Foo
,无法传递到
SetFoo
class Foo1

我能想到的最好办法是通过编程方式生成代理并通过CodeDOM检测重复项,忽略
DataContract
/
WebServiceBinding
名称空间,但这是一个巨大的混乱

[WebService(Namespace = "http://tempuri.org/FOO1")]
public class Service1 : WebService
{
    [WebMethod]
    public Foo GetFoo()
    {
        return new Foo();
    }
}

[WebService(Namespace = "http://tempuri.org/FOO2")]
public class Service2 : WebService
{
    [WebMethod]
    public void SetFoo(Foo foo)
    {
    }
}

public class Foo
{
    public int Bar { get; set; }
}

有一种方法可以做到这一点,如下所述

在您的情况下,可以跳过第一步,从服务1生成代理,然后在生成服务2代理时使用svcutil上的/r标志引用服务1代理程序集

这将确保您的Service2代理将使用来自Service1代理的相同Foo实例

但是,您是否考虑过只托管一个包含两个操作的服务?这会帮你省下很多工作

编辑:也可以看看这篇文章:

首先,您需要为所有公共服务数据类型设置[DataContract(Namespace=“some Namespace here”)],否则在生成WSDL和XSD时,您将拥有来自两个不同名称空间的对象——这是绝对必要的。命名空间值将仅应用于XSD中定义的类型,而不应用于WSDL中定义的类型。XSD=数据,WSDL=服务

当且仅当您设置了元服务行为-添加此行为,然后您可以导航到URL时,才会生成XSD和WSDL。然后,元服务行为的URL将有一个指向WSDL和XSD的链接

我使用下面的代码在windows服务中自托管服务,而不是通过IIS,但是应用相同的主体

/// <summary>
/// Enables meta data output for a service host.
/// </summary>
/// <param name="host">The service host.</param>
/// <remarks>Must be invoked prior to starting the service host.</remarks>
public static void SetupMetaDataBehaviour(ServiceHost host)
{
    ServiceMetadataBehavior metaDataBehaviour = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
    if (metaDataBehaviour == null)
    {
        metaDataBehaviour = new ServiceMetadataBehavior();
        metaDataBehaviour.HttpGetEnabled = true;
        host.Description.Behaviors.Add(metaDataBehaviour);
    }
    else
    {
        metaDataBehaviour.HttpGetEnabled = true;
    }
}
//
///启用服务主机的元数据输出。
/// 
///服务主机。
///必须在启动服务主机之前调用。
公共静态无效SetupMetaDataBehaviour(ServiceHost主机)
{
ServiceMetadataBehavior metaDataBehaviour=host.Description.Behaviors.Find();
if(metaDataBehaviour==null)
{
metaDataBehaviour=新服务Metadatabehavior();
metaDataBehaviour.HttpGetEnabled=true;
host.Description.Behaviors.Add(metaDataBehaviour);
}
其他的
{
metaDataBehaviour.HttpGetEnabled=true;
}
}

添加两个web引用后:

  • 双击第二个web服务引用
  • 在对象浏览器中,导航到Foo的定义
  • 右键单击Foo并选择“转到定义”
  • 删除类Foo的定义
  • 为webservice one的命名空间添加using语句
  • 查找
    .Foo
    的所有实例,并将其替换为
    Foo

  • 这将解决您的问题,因为它强制两个服务引用的自动生成代码使用相同的类声明。

    作为WSDL定义的一部分,是定义类型的XSD。如果它们没有在WSDL中定义,您应该如何使用服务?@hugh它们在每个WSDL中定义两次,因此,给定
    Service1
    Service2
    wsdls,我看不到一种方法可以为它们生成具有通用
    Foo
    定义的代理,该定义可以从
    GetFoo
    传递到
    SetFoo
    。我理解。下面是我的答案。这些类型在不同的名称空间中,所以它们是不同的类型。如果您希望它们是相同的类型,那么就使用相同的名称空间。你只能想象这些类型是相同的。如果服务希望将它们视为相同的类型,那么它们必须将它们放在相同的XML命名空间中。“这不仅仅是一个好主意;这是法律”似乎不起作用,将2个
    Foo
    s保留在两个不同的名称空间中。下面是设置()--一个带有两个服务的
    WebService1
    ,一个带有共享
    Foo
    类型的
    ClassLibrary1
    和一个试图通过代理调用
    GetFoo
    /
    SetFoo
    ConsoleApplication1
    。我尝试了
    svcutil Service1.wsdl&&csc/t:library Service1.cs&&svcutil Service2.wsdl/r:Service1.dll
    svcutil Service1.wsdl/r:..\ClassLibrary1\bin\Debug\ClassLibrary1.dll
    但在这两种情况下都会出现两个不兼容的
    Foo
    s。你能发布wsdl吗?我会看一看一看——可能这两个Foo真的不兼容是在不同的XSD中定义的独立类型,在这种情况下,您不能使用/r标志,因为这些类型不是真正等效的。确切地说,它们来自同一个类,但在技术上是不同的,因为自动生成的wsdl将两个副本放在两个不同的名称空间(使用它们的父web服务)下,因此存在问题。示例WSDL位于Thank,但根据OP,我无法修改服务或类型,我只能访问原始自动生成的WSDL,就好像它们是公共的一样(从技术上讲,我已经反映了我自己生成WSDL的类型),服务上有唯一的[WebService(命名空间)],类型上除了偶尔的XmlInclude之外没有任何内容,没有与服务或命名空间相关的属性。就像
    GetFoo
    /
    SetFoo
    示例一样,我有用于
    Service1
    Service2
    的wsdl,我需要使用共享
    Foo
    为它们生成代理,这样我就可以调用
    GetFoo
    并将其传递到不同自动生成命名空间下的
    SetFoo
    (当我摆弄
    CodeDOM
    、提取
    Foo
    并删除任何名称空间时都可以使用,但这种方法无法扩展到数百个晦涩难懂的传统web服务)。谢谢,但它与后代web服务相同