問題提出:
在WCF中如何?登陸,典型的情境如下:
[ServiceContract]
public interface ILogin {
[OperationContract]
bool Signin(string userName, string password);
}
[ServiceContract]
public interface IBizTest {
[OperationContract]
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)) {
MessageHeader mh = MessageHeader.CreateHeader("HeaderName", string.Empty, "HeaderValue");
OperationContext.Current.OutgoingMessageHeaders.Add(mh);
//…
}
但是每個用戶端都要增加,太麻煩了,所以,引出
2.自訂一個CallContextAttribute,代碼如下:
1. 先定義一個IClientMessageInspector介面的實作類別
public class ContextHeader : IClientMessageInspector {
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {
//
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) {
MessageHeader clientHeader = MessageHeader.CreateHeader("headerName", string.Empty, "headerValue");
request.Headers.Add(clientHeader);
return null;
}
}
OK , 然後就可以實現CallContextAttribute了
public class CallContextAttribute : Attribute, IEndpointBehavior, IOperationBehavior {
IEndpointBehavior Members#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) {
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
clientRuntime.MessageInspectors.Add(new ContextHeader());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) {
}
public void Validate(ServiceEndpoint endpoint) {
}
#endregion
IOperationBehavior Members#region IOperationBehavior Members
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) {
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) {
clientOperation.Parent.MessageInspectors.Add(new ContextHeader ());
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) {
}
public void Validate(OperationDescription operationDescription) {
}
#endregion
}
完工大吉,最後在我們Contract中加入CallContextAttribute就可以啦,用戶端不用增加任何代碼了。
[ServiceContract]
[CallContext]
public interface IBizTest {
[OperationContract]
[CallContext]
string GetWelcomeInfo();
}