如何:使用代码发布服务的元数据
这是讨论为 Windows Communication Foundation (WCF) 服务发布元数据的两个操作方法主题之一。 有两种方式可以指定服务应如何发布元数据:使用配置文件和使用代码。 本主题演示如何使用代码发布服务的元数据。
注意
本主题演示如何以不安全的方式发布元数据。 任何客户端都可以检索服务的元数据。 如果您要求服务以安全方式发布元数据, 请参阅自定义安全元数据终结点。
有关在配置文件中发布元数据的详细信息,请参阅如何使用配置文件发布服务的元数据。 通过发布元数据,客户端可以使用 WS-Transfer GET 请求或使用 ?wsdl
查询字符串的 HTTP/GET 来检索元数据。 若要确保代码能够工作,必须创建一个基本的 WCF 服务。 在以下代码中提供了一个基本的自承载服务。
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Metadata.Samples
{
[ServiceContract]
public interface ISimpleService
{
[OperationContract]
string SimpleMethod(string msg);
}
class SimpleService : ISimpleService
{
public string SimpleMethod(string msg)
{
Console.WriteLine("The caller passed in " + msg);
return "Hello " + msg;
}
}
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Description
<ServiceContract()> _
Public Interface ISimpleService
<OperationContract()> _
Function SimpleMethod(ByVal msg As String) As String
End Interface
Class SimpleService
Implements ISimpleService
Public Function SimpleMethod(ByVal msg As String) As String Implements ISimpleService.SimpleMethod
Console.WriteLine("The caller passed in " + msg)
Return "Hello " + msg
End Function
End Class
在代码中发布元数据
在控制台应用程序的主方法中,通过传入服务类型和基址来实例化 ServiceHost 对象。
ServiceHost svcHost = new ServiceHost(typeof(SimpleService), new Uri("http://localhost:8001/MetadataSample"));
Dim svcHost As New ServiceHost(GetType(SimpleService), New Uri("http://localhost:8001/MetadataSample"))
紧接在步骤 1 的代码下面创建一个 try 块,这将捕获在服务运行过程中引发的任何异常。
try {
Try
} catch (CommunicationException commProblem) { Console.WriteLine("There was a communication problem. " + commProblem.Message); Console.Read(); }
Catch commProblem As CommunicationException Console.WriteLine("There was a communication problem. " + commProblem.Message) Console.Read() End Try
检查服务主机是否已经包含一个 ServiceMetadataBehavior,如果没有,则创建一个新的 ServiceMetadataBehavior 实例。
// Check to see if the service host already has a ServiceMetadataBehavior ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>(); // If not, add one if (smb == null) smb = new ServiceMetadataBehavior();
'Check to see if the service host already has a ServiceMetadataBehavior Dim smb As ServiceMetadataBehavior = svcHost.Description.Behaviors.Find(Of ServiceMetadataBehavior)() 'If not, add one If (smb Is Nothing) Then smb = New ServiceMetadataBehavior() End If
将 HttpGetEnabled 属性设置为
true.
smb.HttpGetEnabled = true;
smb.HttpGetEnabled = True
ServiceMetadataBehavior 包含一个 MetadataExporter 属性。 MetadataExporter 包含一个 PolicyVersion 属性。 将 PolicyVersion 属性的值设置为 Policy15。 还可以将 PolicyVersion 属性设置为 Policy12。 当设置为 Policy15 时,元数据导出程序会使用符合 WS-Policy 1.5 的元数据生成策略信息。 当设置为 Policy12 时,元数据导出程序会生成符合 WS-Policy 1.2 的策略信息。
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15
将 ServiceMetadataBehavior 实例添加到服务主机的行为集合。
svcHost.Description.Behaviors.Add(smb);
svcHost.Description.Behaviors.Add(smb)
将元数据交换终结点添加到服务主机。
// Add MEX endpoint svcHost.AddServiceEndpoint( ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex" );
'Add MEX endpoint svcHost.AddServiceEndpoint( _ ServiceMetadataBehavior.MexContractName, _ MetadataExchangeBindings.CreateMexHttpBinding(), _ "mex")
将应用程序终结点添加到服务主机。
// Add application endpoint svcHost.AddServiceEndpoint(typeof(ISimpleService), new WSHttpBinding(), "");
'Add application endpoint svcHost.AddServiceEndpoint(GetType(ISimpleService), New WSHttpBinding(), "")
注意
如果您不希望向服务添加任何终结点,则运行时为您添加默认终结点。 在此示例中,由于服务的 ServiceMetadataBehavior 设置为
true
,所以服务还启用了发布元数据。 有关默认终结点的详细信息,请参阅简化配置和 WCF 服务的简化配置。打开服务主机并等待传入调用。 当用户按 Enter 时,关闭服务主机。
// Open the service host to accept incoming calls svcHost.Open(); // The service can now be accessed. Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. svcHost.Close();
'Open the service host to accept incoming calls svcHost.Open() 'The service can now be accessed. Console.WriteLine("The service is ready.") Console.WriteLine("Press <ENTER> to terminate service.") Console.WriteLine() Console.ReadLine() 'Close the ServiceHostBase to shutdown the service. svcHost.Close()
生成并运行控制台应用程序。
浏览到服务的基址(本示例中的
http://localhost:8001/MetadataSample
)并验证已打开元数据发布。 你应会看到一个网页,该网页的顶部紧接在“你已创建服务”下面的位置显示“简单服务”。如果没有,则生成的页面顶部会显示一条消息:“此服务的元数据发布当前处于禁用状态”。
示例
下面的代码示例演示如何在代码中实现发布服务的元数据的基本 WCF 服务。
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Metadata.Samples
{
[ServiceContract]
public interface ISimpleService
{
[OperationContract]
string SimpleMethod(string msg);
}
class SimpleService : ISimpleService
{
public string SimpleMethod(string msg)
{
Console.WriteLine("The caller passed in " + msg);
return "Hello " + msg;
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost svcHost = new ServiceHost(typeof(SimpleService), new Uri("http://localhost:8001/MetadataSample"));
try
{
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
svcHost.Description.Behaviors.Add(smb);
// Add MEX endpoint
svcHost.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);
// Add application endpoint
svcHost.AddServiceEndpoint(typeof(ISimpleService), new WSHttpBinding(), "");
// Open the service host to accept incoming calls
svcHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHostBase to shutdown the service.
svcHost.Close();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.Read();
}
}
}
}
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Description
<ServiceContract()> _
Public Interface ISimpleService
<OperationContract()> _
Function SimpleMethod(ByVal msg As String) As String
End Interface
Class SimpleService
Implements ISimpleService
Public Function SimpleMethod(ByVal msg As String) As String Implements ISimpleService.SimpleMethod
Console.WriteLine("The caller passed in " + msg)
Return "Hello " + msg
End Function
End Class
Module Module1
Sub Main()
Dim svcHost As New ServiceHost(GetType(SimpleService), New Uri("http://localhost:8001/MetadataSample"))
Try
'Check to see if the service host already has a ServiceMetadataBehavior
Dim smb As ServiceMetadataBehavior = svcHost.Description.Behaviors.Find(Of ServiceMetadataBehavior)()
'If not, add one
If (smb Is Nothing) Then
smb = New ServiceMetadataBehavior()
End If
smb.HttpGetEnabled = True
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15
svcHost.Description.Behaviors.Add(smb)
'Add MEX endpoint
svcHost.AddServiceEndpoint( _
ServiceMetadataBehavior.MexContractName, _
MetadataExchangeBindings.CreateMexHttpBinding(), _
"mex")
'Add application endpoint
svcHost.AddServiceEndpoint(GetType(ISimpleService), New WSHttpBinding(), "")
'Open the service host to accept incoming calls
svcHost.Open()
'The service can now be accessed.
Console.WriteLine("The service is ready.")
Console.WriteLine("Press <ENTER> to terminate service.")
Console.WriteLine()
Console.ReadLine()
'Close the ServiceHostBase to shutdown the service.
svcHost.Close()
Catch commProblem As CommunicationException
Console.WriteLine("There was a communication problem. " + commProblem.Message)
Console.Read()
End Try
End Sub
End Module