简体   繁体   English

WCF自己的EndpointBehavior读取客户端会话

[英]WCF own EndpointBehavior read client Session

I have an IClientMessageInspector interface with BeforeSendRequest() method implemented. 我有一个实现了BeforeSendRequest()方法的IClientMessageInspector接口。 In this method I want to retrieve the Session object set in the client. 在这种方法中,我想检索客户端中的Session对象集。 Something like. 就像是。

    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;
    }

I think I need something very similar as in this question . 我认为我需要与此问题非常相似的东西。

If both your client application and WCF service are hosted in same application (actually virtual application in IIS), you can share your session state. 如果您的客户端应用程序和WCF服务都托管在同一应用程序(实际上是IIS中的虚拟应用程序)中,则可以共享会话状态。

But you need to enable ASP.Net compability mode within your WCF (see this: https://msdn.microsoft.com/en-us/library/ms752234.aspx ) 但是您需要在WCF中启用ASP.Net兼容模式(请参阅: https : //msdn.microsoft.com/zh-cn/library/ms752234.aspx

If your applications are hosted in different applications, you can still do it, but you must use an external storage for you session, like a Session State server (see more here: https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx ). 如果您的应用程序托管在其他应用程序中,您仍然可以执行此操作,但是您必须为会话使用外部存储,例如会话状态服务器(请参阅此处的更多信息: https : //msdn.microsoft.com/zh-cn/库/ms178586%28v=vs.140%29.aspx )。

You proceed the same way, but you must set in both web.config files the same session storage. 您以相同的方式进行操作,但是必须在两个web.config文件中设置相同的会话存储。

Hope it helps. 希望能帮助到你。

I ended up using an approach like in this tutorial . 我最终使用了本教程中介绍的方法。 I add the relevant information in a cookie as key-value pairs and read it in the service implementation. 我将相关信息作为键值对添加到cookie中,并在服务实现中读取它。 Instead of service reference I am using ChannelFactory , but basically the main idea is the same as in the tutorial. 我使用的是ChannelFactory ,而不是服务参考,但基本上,主要思想与本教程中的相同。

My BeforeSendRequest method is: 我的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;
        }

The binding settings is: 绑定设置为:

            <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>

In the client app I needed (in web.config system.serviceModel ): 在我需要的客户端应用程序中(在web.config system.serviceModel ):

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>

And in the service implementation class annotation: 并在服务实现类中进行注释:

    [AspNetCompatibilityRequirements(RequirementsMode =
    AspNetCompatibilityRequirementsMode.Required)]
    public class MyService : IMyService {
       // ...
    }

For service calls I am using a wrapper object which implements IDisposable , takes case of proper disposal and adding to EndpointBehaior to the ChannelFactory before creating the channel. 对于服务调用,我正在使用实现IDisposable的包装对象,要适当处理,并在创建通道之前将EndpointBehaior添加到ChannelFactory

    _factory = new ChannelFactory<T>( );
    _factory.Endpoint.Behaviors.Add(new CookieEndpointBehavior(cookieStr));
    _channel = _factory.CreateChannel();

I am using the service wrapper class in using block , which will call Dispose , once it reaches out of scope. 我在using blockusing block服务包装器类,一旦超出范围,它将调用Dispose

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM