我跟踪了Carlos Figueira关于WCF自托管服务中客户端跟踪的博客,并尝试将其客户端跟踪器用于IIS托管WCF服务。我在使用扩展类时遇到了一些问题,在创建客户端时,初始化事件永远不会为IChannelInitializer对象触发。
我们的想法是跟踪客户端与IIS中托管的基于会话的WCF服务的连接,我特别想知道客户端何时断开连接,以便我可以清理通过不同服务端点流式传输的一些数据。
在客户端上,我使用Visual Studio的解决方案资源管理器中的“添加服务引用”来生成绑定。
WCF服务实现(Imlvc.cs)
[ServiceContract(SessionMode=SessionMode.Required)]
public interface Imlvc
{
[OperationContract]
int MyMethod();
[OperationContract]
int ConnectedClients();
}
WCF服务(mlvc.svc.cs)
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class mlvc : Imlvc
{
static int m_Counter = 0;
public int MyMethod()
{
m_Counter++;
return m_Counter;
}
public int ConnectedClients()
{
int val = ClientTrackerChannelInitializer.ConnectedClientCount;
Debug.Write("ConnectedClients() called.");
return val;
}
}
public class ClientTrackerChannelInitializer : IChannelInitializer
{
internal static int ConnectedClientCount = 0;
public void Initialize(IClientChannel channel)
{
Debug.Write("Initialize was fired for ClientTrackerChannelInitializer");
ConnectedClientCount++;
channel.Closed += ClientDisconnected;
channel.Faulted += ClientDisconnected;
}
static void ClientDisconnected(object sender, EventArgs e)
{
Debug.Write("ClientDisconnected() was fired for ClientTrackerChannelInitializer");
ConnectedClientCount--;
}
}
public class ClientTrackerEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.ChannelDispatcher.ChannelInitializers.Add(new ClientTrackerChannelInitializer());
Debug.Write("endpointDispatcher added");
}
public void Validate(ServiceEndpoint endpoint) { Debug.Write("endpoint Validate Fired"); }
public override System.Type BehaviorType
{
get
{
Debug.Write("behavior property retrieved");
return typeof(ClientTrackerEndpointBehavior);
}
}
protected override object CreateBehavior()
{
Debug.Write("endpoint behavior created.");
return new ClientTrackerEndpointBehavior();
}
}
服务的Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<customErrors mode="Off" />
<compilation debug="false"/>
</system.web>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="myClientTracker"
type="MasterListWCF.ClientTrackerEndpointBehavior, MasterListWCF" />
</behaviorExtensions>
</extensions>
<services>
<service behaviorConfiguration="sessionBehavior" name="MasterListWCF.mlvc">
<endpoint address="" behaviorConfiguration="myClientTracker"
binding="customBinding" bindingConfiguration="sessionHttpsBindingConfiguration"
name="sessionHttpEndpoint" contract="MasterListWCF.Imlvc" />
<endpoint address="mex" binding="mexHttpBinding" name="mexHttpSessionEndpoint"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://m.managedsp.com/testsvc/mlvc.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="myClientTracker" />
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="sessionBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500"
maxConcurrentInstances="500" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="sessionHttpsBindingConfiguration">
<reliableSession/>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
创建客户端并调用服务方法的控制台应用程序
static void Main(string[] args)
{
ImlvcClient client = new ImlvcClient();
Console.WriteLine(client.State);
Console.WriteLine("Connected clients " + client.ConnectedClients());
Console.WriteLine("My method " + client.MyMethod());
Console.WriteLine("My method " + client.MyMethod());
Console.WriteLine("My method " + client.MyMethod());
Console.WriteLine(client.State);
Console.ReadKey();
}
客户端的app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="myClientTracker"
type="MasterListWCF.ClientTrackerEndpointBehavior, MasterListWCF" />
</behaviorExtensions>
</extensions>
<client>
<endpoint address="https://m.managedsp.com/testsvc/mlvc.svc" behaviorConfiguration="myClientTracker"
binding="customBinding" bindingConfiguration="sessionHttpsBindingConfiguration"
contract="mlvc.Imlvc" name="sessionHttpEndpoint" />
</client>
<bindings>
<customBinding>
<binding name="sessionHttpsBindingConfiguration">
<reliableSession/>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="myClientTracker" />
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
以下是控制台应用的输出
Created
Connected clients 0
My method 1
My method 2
My method 3
Opened
问题是在创建客户端时从不触发initialize事件。这是WCF进程的调试日志。您可以看到调用了ClientConnections,但从未为IChannelInitializer调用initialize方法。
'w3wp.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\testsvc\d85651f1\367baff8\assembly\dl3\edc64503\46551bf1_57d3cf01\MasterListWCF.dll', Symbols loaded.
'w3wp.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Data.Services.Design\v4.0_4.0.0.0__b77a5c561934e089\System.Data.Services.Design.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'w3wp.exe' (Managed (v4.0.30319)): Loaded 'Microsoft.GeneratedCode'
ConnectedClients() called.
The thread '<No Name>' (0x2f0) has exited with code 0 (0x0).
有人能指出我为什么没有触发Initialize方法的正确方向吗?