如何在WCF中使用自定义的Header,(典型场景:业务系统的登陆与使用)
  问题提出:
 [ServiceContract]
[ServiceContract]

 public interface ILogin {
public interface ILogin {

 [OperationContract]
        [OperationContract]

 bool Signin(string userName, string password);
        bool Signin(string userName, string password);

 }
}

 [ServiceContract]
[ServiceContract]

 public interface IBizTest {
public interface IBizTest {

 [OperationContract]
        [OperationContract]

 string GetWelcomeInfo();
        string GetWelcomeInfo();

 }
}
 
 using (OperationContextScope scope = new OperationContextScope(InnerChannel)) {
using (OperationContextScope scope = new OperationContextScope(InnerChannel)) {

 MessageHeader mh = MessageHeader.CreateHeader("HeaderName", string.Empty, "HeaderValue");
                MessageHeader mh = MessageHeader.CreateHeader("HeaderName", string.Empty, "HeaderValue");

 OperationContext.Current.OutgoingMessageHeaders.Add(mh);
                OperationContext.Current.OutgoingMessageHeaders.Add(mh);

 //…
                //…

 }
 }
 
 public class ContextHeader : IClientMessageInspector {
public class ContextHeader : IClientMessageInspector {

 public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {

 //
            //

 }
        }

 public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) {
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) {

 MessageHeader clientHeader = MessageHeader.CreateHeader("headerName", string.Empty, "headerValue");
MessageHeader clientHeader = MessageHeader.CreateHeader("headerName", string.Empty, "headerValue");

 request.Headers.Add(clientHeader);
request.Headers.Add(clientHeader);

 return null;
return null;

 }
}

 }
}

 
 public class CallContextAttribute : Attribute, IEndpointBehavior, IOperationBehavior {
public class CallContextAttribute : Attribute, IEndpointBehavior, IOperationBehavior {

 IEndpointBehavior Members
IEndpointBehavior Members

 IOperationBehavior Members
IOperationBehavior Members

 }
}

 
 [ServiceContract]
[ServiceContract]

 [CallContext]
[CallContext]

 public interface IBizTest {
public interface IBizTest {

 [OperationContract]
        [OperationContract]

 [CallContext]
[CallContext]

 string GetWelcomeInfo();
        string GetWelcomeInfo();

 }
}
 
在WCF中如何实现登陆,典型的场景如下:
 [ServiceContract]
[ServiceContract]
 public interface ILogin {
public interface ILogin {
 [OperationContract]
        [OperationContract]
 bool Signin(string userName, string password);
        bool Signin(string userName, string password);
 }
}
 [ServiceContract]
[ServiceContract]
 public interface IBizTest {
public interface IBizTest {
 [OperationContract]
        [OperationContract]
 string GetWelcomeInfo();
        string GetWelcomeInfo();
 }
}
千万别从WCF自带的那个InstanceContextMode来想办法,因为WCF中的PerSession调用只是针对每个服务类而言的,除非你变态到服务端只有一个类来实现全部的接口;
变个思路,能不能用类似.NET Remoting中的CallContext呢?但是查了一下WCF的手册,好像也没有这么个东西,怎么解决呢?那就是Custom header.
解决方案提出前,需要知道一点的就是,服务端取客户端送出的Header的方法:
先遍历OperationContext.Current.IncomingMessageHeaders找出客户端发送的Header Name,然后再用 OperationContext.Current.IncomingMessageHeaders.GetHeader<T>(i)得到值就可以啦。
下面的问题就剩下客户端怎么发送Custom Header了。
策略1:在每个客户端Proxy中增加类似如下的代码
 using (OperationContextScope scope = new OperationContextScope(InnerChannel)) {
using (OperationContextScope scope = new OperationContextScope(InnerChannel)) {
 MessageHeader mh = MessageHeader.CreateHeader("HeaderName", string.Empty, "HeaderValue");
                MessageHeader mh = MessageHeader.CreateHeader("HeaderName", string.Empty, "HeaderValue");
 OperationContext.Current.OutgoingMessageHeaders.Add(mh);
                OperationContext.Current.OutgoingMessageHeaders.Add(mh);
 //…
                //…
 }
 }
但是每个客户端都要增加,太麻烦了,所以,引出
2.自定义一个CallContextAttribute,代码如下:
1. 先定义一个IClientMessageInspector接口的实现类
 public class ContextHeader : IClientMessageInspector {
public class ContextHeader : IClientMessageInspector {
 public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {
 //
            //
 }
        }
 public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) {
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) {
 MessageHeader clientHeader = MessageHeader.CreateHeader("headerName", string.Empty, "headerValue");
MessageHeader clientHeader = MessageHeader.CreateHeader("headerName", string.Empty, "headerValue");
 request.Headers.Add(clientHeader);
request.Headers.Add(clientHeader);
 return null;
return null;
 }
}
 }
}

OK , 然后就可以实现CallContextAttribute了
 public class CallContextAttribute : Attribute, IEndpointBehavior, IOperationBehavior {
public class CallContextAttribute : Attribute, IEndpointBehavior, IOperationBehavior {
 IEndpointBehavior Members
IEndpointBehavior Members
 IOperationBehavior Members
IOperationBehavior Members
 }
}

完工大吉,最后在我们Contract中加入CallContextAttribute就可以啦,客户端不用增加任何代码了。
 [ServiceContract]
[ServiceContract]
 [CallContext]
[CallContext]
 public interface IBizTest {
public interface IBizTest {
 [OperationContract]
        [OperationContract]
 [CallContext]
[CallContext]
 string GetWelcomeInfo();
        string GetWelcomeInfo();
 }
}
 
                    
                


 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号