将 ASMX 合同转换为 WCF

Converting ASMX contracts to WCF

我有一个旧的 web 服务,我需要将其转换为一个未托管在 IIS 中的新系统,因此我无法直接复制它。我可以创建自托管 WCF 服务,这样我就可以将功能放在那里。 但是,我无法让合同匹配,因为我们已经拥有的客户端在连接到网络服务时出现以下异常:

The message with action 'http://services.mysite.com/MyService/MyMethod' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher.

我在其他一些 SO 帖子中读到,我可以通过 运行 命令提示符中的以下命令确保合同相同:

wsdl.exe /serverInterface http://oldservices.mysite.com/MyService.asmx?WSDL

此命令生成一些代码,according to the documentation、"Generates interfaces for server implementation"。

我将此代码纳入我的新解决方案并启动它(在添加一些额外的属性并美化代码之后),我可以从 WebService Studio 成功调用 MyMethod 并获得预期的结果。然而,老客户仍然抱怨同样的异常。

我必须怎么做才能将旧的 ASMX 网络服务成功转换为完全兼容的 WCF 服务?

WSDL of old ASMX webservice @ Pastebin

Generated Server Interface (from wsdl.exe) @ Pastebin

我调整后的界面

[WebServiceBinding(Name = "MyServiceSoap", Namespace = "http://services.mysite.com/MyService")]
[XmlInclude(typeof(Foo))]
[XmlInclude(typeof(Bar))]
[ServiceContract]
[ServiceKnownType(typeof(Foo))]
[ServiceKnownType(typeof(Bar))]
public interface IMyServiceSoap {

    [OperationContract, XmlSerializerFormat(Style = OperationFormatStyle.Document)]
    [WebMethod]
    [SoapDocumentMethod("http://services.mysite.com/MyService/MyMethod", RequestNamespace = "http://services.mysite.com/MyService", ResponseNamespace = "http://services.mysite.com/MyService", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

    ReturnMessage MyMethod();
}

我调整后的类型定义

[Serializable]
[XmlType(Namespace = "http://services.mysite.com/MyService")]
public class ReturnMessage {
    public ReturnStatus Status { get; set; }
    public object GenericReturn { get; set; }
}

[Serializable]
[XmlType(Namespace = "http://services.mysite.com/MyService")]
public enum ReturnStatus {
}

[Serializable]
[XmlType(Namespace = "http://services.mysite.com/MyService")]
public class Foo {
    public string Text { get; set; }
}

[Serializable]
[XmlType(Namespace = "http://services.mysite.com/MyService")]
public class Bar {
    public int Number{ get; set; }
}

实施class

public class MyServiceSoap : IMyServiceSoap {
    public ReturnMessage MyMethod() {
        return new ReturnMessage() { Status = ReturnStatus.OK, GenericReturn = new Foo() };
    }
}

WCF 启动器

ServiceHost host = new ServiceHost(typeof(MyServiceSoap), new Uri("http://localhost:8080/MyService.asmx"));
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy12;
host.Description.Behaviors.Add(smb);
host.Open();

我终于在另一个论坛上得到了正确方向的推动,这让我指向 this page。 我之前发现的关于 wsdl.exe 的内容被证明是不正确的。相反,您必须 运行 以下命令:

SvcUtil.exe /serviceContract http://oldservices.mysite.com/MyService.asmx?WSDL

这会生成一个您可以调整和美化的文件(只是不要更改任何类名)。

然后像我上面那样启动WCF服务,多了一行:

smb.ExternalMetadataLocation = new Uri("http://localhost:8080/wsdl/MyService.wsdl");

此处引用的 WSDL 文件必须与您的旧服务生成的 WSDL 相同。只需将自动生成的 WSDL 文件保存到您的新服务器,并记住更改文件底部的地址位置以指向您的新服务(而不是旧服务),您就可以开始了!