.NET 2 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用

Posted

技术标签:

【中文标题】.NET 2 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用【英文标题】:.NET 2 ASMX Web Service - Invoked via .NET 3.5 Service Reference - Common Class Reuse 【发布时间】:2011-08-28 05:55:57 【问题描述】:

我有一个 .NET 2 Web 服务,它带有一个类似这样的 Web 方法:

[WebMethod]
public Common.foobar DoSomething(Common.foobar foo)

foobar 类在通用 .NET 2 程序集中定义,该程序集也可用于(作为项目引用)通过服务引用(不是 .NET 兼容性 Web 引用)调用 Web 服务的 .NET 3.5 应用程序。

问题在于服务引用命名空间包含其自己的自动生成的 foobar 实现。因此,代理 SOAP 客户端上可用的自动生成的服务引用方法具有以下签名:

ServiceReference.foobar DoSomething(ServiceReference.foobar foo)

谷歌搜索告诉我这是不可避免的,因为 Web 服务是基于 .NET 2 的,因此不支持像在 WCF 中那样重用公共类。

所以问题是:有人知道将 Common.foobar 类克隆到 WebServiceReference.foobar 类的简单可靠的方法吗?或者,有人知道我可以使用公共库中定义的类的“hack”吗?或者,任何人都可以指出我在哪里错过了树木的木材,实际上可以使用公共库类

编辑 - 更多信息

.NET 2 webservice 类如下所示:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService

    [WebMethod]
    public CommonLibrary.Foobar DoSomething(CommonLibrary.Foobar foo)
    
        return new CommonLibrary.Foobar()  Data = "Data in common foobar class", EventCode = 1, MessageId = "mid" ;
    

调用客户端(.NET 3.5 - 带有对 .NET 服务的服务引用)如下所示:

static void Main(string[] args)

    // Create the soap client for the .NET 2 service using the auto generated proxy class
    var serviceClient = new NET2WebService_ServiceReference.Service1SoapClient();

    //Just checking that there is a project reference to CommonLibrary
    var commonFoobar_Request = new CommonLibrary.Foobar()
    
        Data = "Common foobar data",
        EventCode = 1,
        MessageId = "Common foobar message id"
    ;

    // This doesn't work as the Service Reference client does not accept the
    // common foobar class.
    /*
    var commonFoobar_Response = serviceClient.DoSomething(commonFoobar_Request);
    Console.WriteLine(commonFoobar_Response.Data);
    */

    // This is the proxy class to foobar generated by the Service Reference
    var serviceRefFoobar_Request = new NET2WebService_ServiceReference.Foobar()
    
        Data = "Common foobar data",
        EventCode = 1,
        MessageId = "Common foobar message id"
    ;

    // This does work as it does uses the autogenerated Foobar class in the service
    // reference
    var serviceRefFoobar_Response = serviceClient.DoSomething(serviceRefFoobar_Request);
    Console.WriteLine(serviceRefFoobar_Response.Data);

通用库(也是 .NET 2)中的 foobar 类如下所示:

public partial class Foobar

    private string dataField;
    private int eventCodeField;
    private string messageIdField;

    public string Data
    
        get
        
            return this.dataField;
        
        set
        
            this.dataField = value;
        
    

    public int EventCode
    
        get
        
            return this.eventCodeField;
        
        set
        
            this.eventCodeField = value;
        
    

    public string MessageId
    
        get
        
            return this.messageIdField;
        
        set
        
            this.messageIdField = value;
        
    

并且是从如下所示的模式派生而来的:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="Foobar">
        <xs:annotation>
            <xs:documentation>Comment describing your root element</xs:documentation>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Data" type="xs:string"/>
                <xs:element name="EventCode" type="xs:int"/>
            </xs:sequence>
            <xs:attribute name="MessageId" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

最后,这是 .NET 3.5 客户端上的服务参考配置页面的屏幕截图:

您可以从该屏幕截图中看到,服务配置以及客户端项目都知道包含我的 Foobar 类实现的 CommonLibrary。

值得一提的是,上面发布的所有内容都有效,但实际上 foobar 类比此处发布的示例要复杂得多。因此,我渴望找到一个解决方案,让我可以在整个框架中使用 Common.foobar,而不必为请求翻译 Common.Foobar => ServiceReference.Foobar,反之亦然。

【问题讨论】:

请尝试使用[DataMember][DataContract] 装饰您的CommonLibrary.Foobar 类的属性。 无法做到这一点,因为 DataMember/DataContract 是随 WCF 和 .NET 3.5 引入的 - 通用库是 .NET 2,因为它由 .NET 2 Web 服务使用。升级.NET的版本是不可行的(事实上如果有可能我会在双方都使用WCF并放弃ASMX) 为什么不把共享类移动到一个新的程序集中并在服务器端和客户端都引用它呢?我就是这么做的。 【参考方案1】:

我所读到的关于 ASMX Web 服务的所有内容都表明它们不支持在客户端重用类型的功能。此功能仅在服务是 WCF 服务而不是旧版 ASMX 服务时存在。

也许是因为 WCF 使用了差异序列化程序,但我不确定。

是否可以将您的 ASMX Web 服务转换为 WCF 服务?

【讨论】:

正如我所希望的那样,WCF 不可能像框架(非常大)那样被部署为仅支持 .NET 2。【参考方案2】:

类的重用是客户端的功能,而不是服务器端的功能。如果您的客户端代码引用了相同的程序集,并且您在使用“添加服务引用”时启用了共享,那么这可能会起作用。

【讨论】:

“这可能有效” - 似乎不行 - 引用是服务引用而不是 .NET 2 兼容性 Web 服务引用。 选中引用程序集中的重用类型,并选择所有引用程序集中的重用类型选项。然而,服务参考已经生成了自己的 .NET 2 ASMX Web 服务所需对象的等价物 @MrEyes:你确定客户项目有你想要共享的类型的程序集作为项目参考吗? 是的,为了在更大更复杂的框架之外进行测试,我创建了一个测试解决方案,其中包含一个 .NET 2 通用库、.NET 2 ASMX Web 服务、.NET 3.5 控制台应用程序,它调用ASMX 通过服务参考。 webservice 和控制台项目都引用了公共库——同样的问题发生了——这个示例项目可以在这里找到:therevcounter.com/ServiceReferenceTest.zip 上一条评论中的链接不再可用,我已经更新了原始问题的更多信息

以上是关于.NET 2 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用的主要内容,如果未能解决你的问题,请参考以下文章

.NET 3.5 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用

无法从 .net 中的 Ajax 调用 .asmx Web 服务

使用 ajax() 和 jsonp 调用 asp.net 远程 Web 服务 .asmx 时出现意外令牌 <

从 Web 服务 (asmx) 页面引用 asp.net 页面上的字段

如何使用 Retrofit 在 android 中调用图像上传 Web 服务 (ASP.NET) .asmx 文件

选择啥? .net 3.5 中的 ASMX Web 服务或 WCF?