WCF技术内幕 第4章 (2)

本文介绍如何在WCF中通过创建特定终结点来暴露服务元数据,并使用svcutil.exe工具从运行的服务中获取元数据,自动生成代理类及配置文件。

暴露元数据

在大部分现实世界的应用系统里,有这样一个需求,即发送者询问接收者的终结点并提取元数据,然后使用这些元数据构建能发送给接收终结点消息的基础结构。

如果决定暴露系统的元数据,可以构建一个暴露元数据的终结点,而构建元数据终结点的方式和其他终结点非常相似:使用地址,绑定和契约(ABC)。

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

using WCFServices;

namespace MetaDataApp
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost svc = new ServiceHost(typeof(HelloWCFService));

            //创建ServiceMetadataBehavior
            ServiceMetadataBehavior behavior=new ServiceMetadataBehavior();
            svc.Description.Behaviors.Add(behavior);

            //创建元数据绑定
            Binding binding = MetadataExchangeBindings.CreateMexTcpBinding();
            Uri address = new Uri("net.tcp://localhost:5000/IHelloWCFContract/Mex");

            svc.AddServiceEndpoint(typeof(IHelloWCFContract), binding, address);

            svc.Open();
            Console.ReadKey();
        }
    }
}

使用元数据

svcutil.exe的一个功能是询问一个运行的哦消息应用并基于获得的信息生成代理。由于接收程序暴露了一个元数据终结点,所以可以把svcutil.exe指向运行的终结点。svcutil.exe会自动生成一个代理类型和与服务终结点兼容的配置信息,这些信息都是根据元数据生成的。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WCFServices.HelloWCFService">
        <endpoint address="" binding="wsHttpBinding" contract="WCFServices.IHelloWCFContract"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/IHelloWCFContract" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" httpGetUrl="http://localhost:8732/IHelloWCFContract/metadata"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Svcutil.exe会创建两个文件:HelloWCFService.cs和output.config。

C:\Users\v-xufeif>svcutil /target:code http://localhost:8732/IHelloWCFContract/M
ex
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 4.0.30319.1]
Copyright (c) Microsoft Corporation.  All rights reserved.

Attempting to download metadata from 'http://localhost:8732/IHelloWCFContract/Me
x' using WS-Metadata Exchange or DISCO.
Generating files...
C:\Users\v-xufeif\HelloWCFService.cs
C:\Users\v-xufeif\output.config

为了掩饰如何利用svcutil创建数据,需要创建另一个发送信息控制台程序,命名为ClientApp。这里要重命名配置文件以便发送程序可以读取该配置文件(修改为App.config)。

output.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IHelloWCFContract" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8111/IHelloWCFContract" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IHelloWCFContract" contract="IHelloWCFContract"
                name="WSHttpBinding_IHelloWCFContract">
                <identity>
                    <userPrincipalName value="v-xufeif@fareast.corp.microsoft.com" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

HelloWCFService.cs

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.296
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------



[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IHelloWCFContract")]
public interface IHelloWCFContract
{
    
    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHelloWCFContract/Say", ReplyAction="http://tempuri.org/IHelloWCFContract/SayResponse")]
    void Say(string value);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IHelloWCFContractChannel : IHelloWCFContract, System.ServiceModel.IClientChannel
{
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class HelloWCFContractClient : System.ServiceModel.ClientBase<IHelloWCFContract>, IHelloWCFContract
{
    
    public HelloWCFContractClient()
    {
    }
    
    public HelloWCFContractClient(string endpointConfigurationName) : 
            base(endpointConfigurationName)
    {
    }
    
    public HelloWCFContractClient(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress)
    {
    }
    
    public HelloWCFContractClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress)
    {
    }
    
    public HelloWCFContractClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress)
    {
    }
    
    public void Say(string value)
    {
        base.Channel.Say(value);
    }
}

Client Entry Point:

using System;

namespace ClientApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Press ENTER when the receiver is ready");
            Console.ReadKey();


            Console.WriteLine("Sending a message to the receiver");

            HelloWCFContractClient proxy = new HelloWCFContractClient();

            proxy.Say("NI DA YE DE, WCF!!!");
            proxy.Close();

            Console.WriteLine("Finished sending a message to the receiver");

            Console.ReadKey();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值