WCF自带的EndpointBehavior读取客户端Session
WCF own EndpointBehavior read client Session
我有一个 IClientMessageInspector
接口,实现了 BeforeSendRequest()
方法。
在此方法中,我想检索客户端中设置的 Session
对象。有点像。
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
//Instantiate new HeaderObject with values from ClientContext;
var dataToSend = new MyCustomHeader
{
MyValue = HowDoIGetClientSession["abcValue"];
};
var typedHeader = new MessageHeader<CustomHeader>(dataToSend);
var untypedHeader = typedHeader.GetUntypedHeader("custom-header", "s");
request.Headers.Add(untypedHeader);
return null;
}
我想我需要一些与 this question 非常相似的东西。
如果您的客户端应用程序和 WCF 服务都托管在同一应用程序(实际上是 IIS 中的虚拟应用程序)中,您可以共享会话状态。
但是您需要在 WCF 中启用 ASP.Net 兼容模式(参见:https://msdn.microsoft.com/en-us/library/ms752234.aspx)
如果您的应用程序托管在不同的应用程序中,您仍然可以这样做,但您必须为会话使用外部存储,例如会话状态服务器(在此处查看更多信息:https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx)。
您以相同的方式进行,但您必须在两个 web.config 文件中设置相同的会话存储。
希望对您有所帮助。
我最终使用了 this tutorial 中的方法。
我将相关信息作为键值对添加到cookie中,并在服务实现中读取。我使用 ChannelFactory
而不是服务参考,但基本上主要思想与教程中的相同。
我的BeforeSendRequest
方法是:
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
System.ServiceModel.IClientChannel channel)
{
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name
, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
if (string.IsNullOrEmpty(httpRequestMessage.Headers["Cookie"]))
{
httpRequestMessage.Headers["Cookie"] = cookie;
}
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
httpRequestMessage.Headers.Add("Cookie", cookie);
request.Properties.Add(HttpRequestMessageProperty.Name
, httpRequestMessage);
}
return null;
}
绑定设置为:
<basicHttpBinding>
<binding name="basicHttp" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="20000000" maxBufferSize="20000000" maxReceivedMessageSize="20000000"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"
messageEncoding="Text">
<readerQuotas maxDepth="32" maxStringContentLength="200000000" maxArrayLength="200000000"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
在我需要的客户端应用程序中(在 web.config
system.serviceModel
中):
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
并且在服务实现中class注解:
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Required)]
public class MyService : IMyService {
// ...
}
对于服务调用,我正在使用实现 IDisposable
的包装器对象,在创建通道之前进行适当处理并添加到 EndpointBehaior
到 ChannelFactory
。
_factory = new ChannelFactory<T>( );
_factory.Endpoint.Behaviors.Add(new CookieEndpointBehavior(cookieStr));
_channel = _factory.CreateChannel();
我在 using block
中使用服务包装器 class,一旦超出范围,它将调用 Dispose
。
我有一个 IClientMessageInspector
接口,实现了 BeforeSendRequest()
方法。
在此方法中,我想检索客户端中设置的 Session
对象。有点像。
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
//Instantiate new HeaderObject with values from ClientContext;
var dataToSend = new MyCustomHeader
{
MyValue = HowDoIGetClientSession["abcValue"];
};
var typedHeader = new MessageHeader<CustomHeader>(dataToSend);
var untypedHeader = typedHeader.GetUntypedHeader("custom-header", "s");
request.Headers.Add(untypedHeader);
return null;
}
我想我需要一些与 this question 非常相似的东西。
如果您的客户端应用程序和 WCF 服务都托管在同一应用程序(实际上是 IIS 中的虚拟应用程序)中,您可以共享会话状态。
但是您需要在 WCF 中启用 ASP.Net 兼容模式(参见:https://msdn.microsoft.com/en-us/library/ms752234.aspx)
如果您的应用程序托管在不同的应用程序中,您仍然可以这样做,但您必须为会话使用外部存储,例如会话状态服务器(在此处查看更多信息:https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx)。
您以相同的方式进行,但您必须在两个 web.config 文件中设置相同的会话存储。
希望对您有所帮助。
我最终使用了 this tutorial 中的方法。
我将相关信息作为键值对添加到cookie中,并在服务实现中读取。我使用 ChannelFactory
而不是服务参考,但基本上主要思想与教程中的相同。
我的BeforeSendRequest
方法是:
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
System.ServiceModel.IClientChannel channel)
{
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name
, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
if (string.IsNullOrEmpty(httpRequestMessage.Headers["Cookie"]))
{
httpRequestMessage.Headers["Cookie"] = cookie;
}
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
httpRequestMessage.Headers.Add("Cookie", cookie);
request.Properties.Add(HttpRequestMessageProperty.Name
, httpRequestMessage);
}
return null;
}
绑定设置为:
<basicHttpBinding>
<binding name="basicHttp" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="20000000" maxBufferSize="20000000" maxReceivedMessageSize="20000000"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"
messageEncoding="Text">
<readerQuotas maxDepth="32" maxStringContentLength="200000000" maxArrayLength="200000000"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
在我需要的客户端应用程序中(在 web.config
system.serviceModel
中):
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
并且在服务实现中class注解:
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Required)]
public class MyService : IMyService {
// ...
}
对于服务调用,我正在使用实现 IDisposable
的包装器对象,在创建通道之前进行适当处理并添加到 EndpointBehaior
到 ChannelFactory
。
_factory = new ChannelFactory<T>( );
_factory.Endpoint.Behaviors.Add(new CookieEndpointBehavior(cookieStr));
_channel = _factory.CreateChannel();
我在 using block
中使用服务包装器 class,一旦超出范围,它将调用 Dispose
。