科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件ASMX2.0、WSE3.0和WCF问题解答(一)

ASMX2.0、WSE3.0和WCF问题解答(一)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

 Microsoft® .NET Framework 2.0 版通过几个有趣但可能令人困惑的方式重塑了 Web 服务的前景。

作者:MSDN 来源:IT专家网 2008年6月6日

关键字: WCF WSE ASM net Windows

  • 评论
  • 分享微博
  • 分享邮件
Microsoft® .NET Framework 2.0 版通过几个有趣但可能令人困惑的方式重塑了 Web 服务的前景。因此,本月我打算解答一些与 ASP.NET Web Services (ASMX) 2.0、Web Services Enhancements (WSE) 3.0 和 Windows® Communication Foundation (WCF)(WinFX® 的一部分)有关的最常见问题。(查看第二部分

  问:能解释一下支持接口的新 ASMX 2.0 的工作方式吗?哪些属性用于接口,哪些属性用于类?

  答:.NET Framework 2.0 中的 ASMX 框架引入了一个重大的编程模型改进:能够在 .NET 接口定义中定义 Web 服务协定。此功能允许您使用常规的 System.Web.Services 属性([WebServiceBinding]、[WebMethod]、[SOAPDocumentMethod] 等)来批注 .NET 接口定义。然后,您就可以在 .NET 类上实现 .NET 接口,以有效地实现服务协定。

  该方法与 WCF 中的方法(主要区别是属性名不同)十分类似。它允许您从实现代码中去耦服务协定,从而使管理和重用变得更加方便,也使代码的可读性更高。如下显示该方法的一个示例。

using System.Web.Services;

[WebServiceBinding(
    Name = "QuoteService",
    Namespace = "http://example.org/stocks",
    ConformsTo = WsiProfiles.BasicProfile1_1,
    EmitConformanceClaims=true)]
public interface IQuoteService
{
    [WebMethod]
    StockQuote GetQuote(string symbol);
    [WebMethod]
    List<StockQuote> GetQuotes(List<string> symbols);
}

[WebService(Namespace="http://example.org/stocks")]
public class QuoteService : IQuoteService
{
    public StockQuote GetQuote(string symbol)
    {
        ... // retrieve and return new StockQuote
    }
    public List<StockQuote> GetQuotes(List<string> symbol)
    {
        ... // retrieve and return List<StockQuote>
    }
}

  [WebServiceBinding] 和 [WebMethod] 用于接口,而 [WebService] 用于类。使用此模型时,影响服务协定定义的所有属性都必须置于接口定义(而不是类)中。这包括 [SOAPDocumentService]、[SOAPDocumentMethod] 以及能够应用于方法签名的各种 System.XML.Serialization 属性。您不能跨接口和类定义混合和匹配这些属性,ASMX 将帮助您确保这一点。 例如,一旦您从接口派生了一个包含这些服务协定属性的类之后,ASMX 将在运行时检查该类以确保您没有使用可能会在将来更改服务协定的任何附加属性。如果 ASMX 发现了此类附加属性,它将显示一个错误,指出您违反了模型。

  ASMX 服务属性用法错误

  虽然这最小化了需要在派生类上使用的属性数量,但仍有一些需要用于配置服务终结点。您将在类上使用 [WebService] 来指定终结点的 详细信息。这很有意义,原因是您可以让多个服务实现同一个服务协定。同样,如果您使用 WSE 3.0,则应在类上使用 [Policy] 将安全策略配置应用于特定的终结点。

  但在某些情况下,如果需要通过各种 [WebMethod] 属性(BufferResponse、CacheDuration、EnableSession、TransactionOption)来配置本地处理行为,您可能还需要在派生方法上使用 [WebMethod]。例如,如下所示的代码中,我使用 [WebMethod] 来配置响应缓存。

[WebService(Namespace="http://example.org/stocks")]
public class QuoteService : IQuoteService
{
    [WebMethod(CacheDuration=60)]
    public StockQuote GetQuote(string symbol)
    {
        ... // retrieve and return new StockQuote
    }
    [WebMethod(CacheDuration=60)]
    public List<StockQuote> GetQuotes(List<string> symbol)
    {
        ... // retrieve and return List<StockQuote>
    }
}

  此处使用 [WebMethod] 不会影响服务协定。它只配置本地处理行为。在该上下文中使用 [WebMethod] 时,您只能使用这些行为属性,并且必须避免能够修改服务协定的任何属性。 问:如何在自定义应用程序中承载 ASMX 2.0 类(不使用 IIS)?

  答:在 MSDN®Magazine 2004 年 12 月的专栏 (Service Station: Run ASMX Without IIS) 中,我讨论了如何利用 HTTP.sys 和 .NET Framework 2.0 中新的 HTTPListener 类在自己的应用程序中宿主 ASP.NET 管道。这是一个重要的任务,也是在自己的应用程序中于 IIS 外部重用 ASMX 类的唯一方式。但 WSE 3.0 与之完全不同。

  WSE 3.0 通过它的消息处理层和宿主模型合并了新的和改进后的 ASMX 2.0 编程模型。这可以通过任何支持 WSE 的传输(如 TCP)在自己的应用程序中宿主 ASMX 终结点。这意味着,现在我可以在 Windows 服务、Windows 窗体应用程序甚至控制台应用程序中承载如图 1所示的 ASMX 代码。代码很简单 — 只需调用 SOAPReceivers.Add 并提供 ASMX 类即可,如下所示:

class Program {
    static void Main(string[] args) {
        Uri uri = new Uri("SOAP.tcp://localhost:9393/quoteservice");
        SOAPReceivers.Add(uri, typeof(QuoteService));
        Console.WriteLine("Listening...");
        Console.ReadLine();
    }
}

  这与 WCF 模型非常类似,您可以使用 ServiceHost 在任何宿主环境中承载服务类型。但您先不要激动,我应该指出,您不能像对待 WCF 中的 ServiceHost 那样将 HTTP 地址提供给 SOAPReceivers.Add。SOAPReceivers 不提供与 HTTP.sys 的直接集成,而这正是本例所需的。因此,要通过 HTTP 承载 ASMX 服务,您必须转换为 映射或者自己编写 HTTP.sys 集成代码。问:WCF 为开发人员提供了哪些 ASMX 2.0 和 WSE 3.0 所没有的功能?

  答:ASMX 2.0 和 WSE 3.0 提供了许多重要功能,但某些开发人员错误地认为这些功能只属于 WCF。例如,它们的堆栈都提供了类似的基于属性的编程模型,其中,您可以根据 .NET 接口定义编写服务协定(参见本专栏的第一个问题和解答)。它们的堆栈都提供与传输方式无关的 SOAP 实现,可以随附多个传输信道和自定义传输挂钩。它们的堆栈都允许在任何基于 Windows 的应用程序中承载服务(通过 WSE 中的 SOAPReceivers 或 WCF 中的 ServiceHost)。它们的堆栈都提供多个消息编码方式,包括两个最广泛受支持的编码方式:XML 1.0 和消息传输优化机制 (MTOM)。它们的堆栈都支持基于消息的安全性,并且可通过简单的配置元素进行配置(能够立即启用的安全性配置文件)。图 4 中的表格总结了堆栈的比较方式。

Feature ASMX 2 .0 plus WSE 3. 0 WCF
Hosting IIS/ASP.NET (.asmx)
SoapReceivers
IIS/ASP.NET (.svc)
ServiceHost<T>
WAS
Programming Model [WebService], [WebMethod], and so on (supports interfaces, generics, and the like) [ServiceContract], [OperationContract], and so on (supports interfaces, generics, and so on)
Message Exchange Patterns (MEP) One-way
Request-response
Custom (using WSE API)
One-way
Request-response
First/last-operation
Duplex
Custom
XML Serialization System.Xml
.Serialization
System.Runtime
.Serialization
System.Xml.Serialization
(you can choose)
Encodings XML 1.0
MTOM
DIME
Custom
XML 1.0
MTOM
Binary
Custom
Transports HTTP
TCP
Custom
HTTP
TCP
Named pipes
MSMQ
P2P
Custom
Protocols Security Security
Reliable messaging
Transactions
Behaviors (enabled via attributes or configuration Local DTC transactions
HTTP buffering
HTTP caching
HTTP sessions
Custom (via SoapExtensions, WSE filters)
Concurrency
Instancing
Throttling
Thread-binding
Exception handling and faults
Impersonation
Session management
Transaction behaviors
Custom (via behavior types)

  堆栈的主要不同之处在于它们对各种 WS-* 规范的支持。WSE 3.0 仅支持安全框架,而 WCF 支持安全框架、可靠消息处理框架和事务框架。如表格所示,WCF 还提供更多的本地处理行为和自定义挂钩。实际上,WCF 对象模型中的每一层都可以通过代码、属性或配置进行扩展。

  最终,WCF 提供更完整的开发框架,该框架是围绕各种 Web 服务协议从头开始设计的。现在,如果使用 ASMX 2.0 和 WSE 3.0,您仍然可以获得非常类似的体验。此外,未来迁移的前景也很看好。 问:将 ASMX 代码移植到 Windows Communication Foundation 困难吗?

  答:当然不困难,除非您认为更改属性名很困难。将 ASMX 代码移到 WCF 是一个机械过程,如果需要,您甚至可以在一定程度上自动化。该过程需要将各种 System.Web.Services 和 System.Web.Services.Protocols 属性转换为等效的 System.ServiceModel 属性。如下显示一个示例,说明如何将第一段代码中的 ASMX 代码移植到 WCF。

using System.ServiceModel;

[ServiceContract(
    Name = "QuoteService",
    Namespace = "http://example.org/stocks",
    FormatMode = ContractFormatMode.XmlSerializer)]
public interface IQuoteService
{
    [OperationContract]
    StockQuote GetQuote(string symbol);
    [OperationContract]
    List<StockQuote> GetQuotes(List<string> symbols);
}

public class QuoteService : IQuoteService
{
    public StockQuote GetQuote(string symbol)
    {
        ... // retrieve and return new StockQuote
    }
}

  这两个框架都支持对类定义或单独的接口定义进行批注,因此额外的重构并不是必需的,但可能有这方面的需要。此外,通过使用 FormatMode=ContractFormatMode.XMLSerializer,如果不需要,您则不必将所有消息类型移植到新的 [DataContract] 模型。随着 WCF 发布日期的临近,Microsoft 将公布更多详细的迁移细节。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章