Last active
April 5, 2016 06:33
-
-
Save kkoziarski/d092f23266ea9658d76c to your computer and use it in GitHub Desktop.
WCF Behavior Extension - validation on methods invoking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace WCFBehaviorExtension | |
{ | |
using System; | |
using System.Collections.ObjectModel; | |
using System.Diagnostics; | |
using System.ServiceModel; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Description; | |
using System.ServiceModel.Dispatcher; | |
public class CustomValidationOperationInvoker : IOperationInvoker, IParameterInspector | |
{ | |
private readonly IOperationInvoker originalInvoker; | |
private readonly string operationName; | |
public CustomValidationOperationInvoker(DispatchOperation operation, OperationDescription operationDescription) | |
{ | |
this.originalInvoker = operation.Invoker; | |
this.operationName = operation.Name; | |
} | |
#region IOperationBehavior Members | |
public object Invoke(object instance, object[] inputs, out object[] outputs) | |
{ | |
OperationContext operationContext = OperationContext.Current; | |
ServiceSecurityContext securityContext = ServiceSecurityContext.Current; | |
// VALIDATION LOGIC GOES HERE | |
string user = null; | |
bool isAnonymous = true; | |
if (securityContext != null) | |
{ | |
user = securityContext.PrimaryIdentity.Name; | |
isAnonymous = securityContext.IsAnonymous; | |
} | |
Uri remoteAddress = operationContext.Channel.LocalAddress.Uri; | |
string sessionId = operationContext.SessionId; | |
MessageVersion messageVersion = operationContext.IncomingMessageVersion; | |
Trace.WriteLine("Username: " + user); | |
Trace.WriteLine("Is Anonymoys" + isAnonymous); | |
Trace.WriteLine("Server address: " + remoteAddress); | |
Trace.WriteLine("Session id: " + sessionId); | |
Trace.WriteLine("Message version: " + messageVersion); | |
Trace.WriteLine("Operation:" + this.operationName); | |
Trace.WriteLine("Arguments:"); | |
foreach (object input in inputs) | |
Trace.WriteLine(input); | |
object result = this.originalInvoker.Invoke(instance, inputs, out outputs); | |
return result; | |
} | |
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) | |
{ | |
return this.originalInvoker.InvokeBegin(instance, inputs, callback, state); | |
} | |
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult asyncResult) | |
{ | |
object result = this.originalInvoker.InvokeEnd(instance, out outputs, asyncResult); | |
return result; | |
} | |
public object[] AllocateInputs() | |
{ | |
return this.originalInvoker.AllocateInputs(); | |
} | |
public bool IsSynchronous | |
{ | |
get { return this.originalInvoker.IsSynchronous; } | |
} | |
#endregion | |
#region IParameterInspector Members | |
public object BeforeCall(string operationName, object[] inputs) | |
{ | |
return null; | |
} | |
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) | |
{ | |
} | |
#endregion | |
} | |
#region OperationBehavior - add as attribute on method (operation) | |
/// <summary> | |
/// Use this to add validation to a single method, instead of all methods in servie | |
/// Example usage - add as attribute on method (operation): | |
/// *[OperationContract] | |
/// *[CustomValidationOperation] | |
/// *string Reverse(string input); | |
/// </summary> | |
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] | |
public class CustomValidationOperationAttribute : Attribute, IOperationBehavior | |
{ | |
public bool IncludeParameterInspector { get; set; } | |
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) | |
{ | |
var invoker = new CustomValidationOperationInvoker(dispatchOperation, operationDescription); | |
dispatchOperation.Invoker = invoker; | |
if (this.IncludeParameterInspector) | |
{ | |
dispatchOperation.ParameterInspectors.Add(invoker); | |
} | |
} | |
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) {} | |
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) {} | |
public void Validate(OperationDescription operationDescription) {} | |
} | |
#endregion | |
#region ServiceBehavior - add as attribute on Service implementation class | |
/// <summary> | |
/// Use this to add validation to all methods (operations) in the service | |
/// Example usage - add as attribute on Service implementation class: | |
/// [CustomValidationServiceBehavior] | |
/// public class ExampleService : IExampleService | |
/// </summary> | |
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] | |
public class CustomValidationServiceBehaviorAttribute : Attribute, IServiceBehavior | |
{ | |
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) | |
{ | |
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints) | |
{ | |
foreach (OperationDescription operation in endpoint.Contract.Operations) | |
{ | |
IOperationBehavior behavior = new CustomValidationOperationBehavior(); | |
operation.Behaviors.Add(behavior); | |
} | |
} | |
} | |
public void AddBindingParameters( | |
ServiceDescription serviceDescription, | |
ServiceHostBase serviceHostBase, | |
Collection<ServiceEndpoint> endpoints, | |
BindingParameterCollection bindingParameters) | |
{ | |
} | |
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } | |
} | |
public class CustomValidationOperationBehavior : IOperationBehavior | |
{ | |
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) | |
{ | |
var invoker = new CustomValidationOperationInvoker(dispatchOperation, operationDescription); | |
dispatchOperation.Invoker = invoker; | |
if (this.IncludeParameterInspector) | |
{ | |
dispatchOperation.ParameterInspectors.Add(invoker); | |
} | |
} | |
public bool IncludeParameterInspector { get; set; } | |
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } | |
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } | |
public void Validate(OperationDescription operationDescription) { } | |
} | |
#endregion | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace WCFBehaviorExtension | |
{ | |
using System; | |
using System.ServiceModel; | |
[ServiceContract] | |
public interface IExampleService | |
{ | |
[OperationContract] | |
//[CustomValidationOperation] | |
string Reverse(string input); | |
} | |
[CustomValidationServiceBehavior] | |
public class ExampleService : IExampleService | |
{ | |
public string Reverse(string input) | |
{ | |
return new string(input.Reverse().ToArray()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment