Last active
April 5, 2016 06:33
-
-
Save kkoziarski/cc7c18e10af38fc9ab01 to your computer and use it in GitHub Desktop.
WCF Behavior Extension - validation on methods invoking.
Generic (base-implementation) version
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.ServiceModel; | |
using System.ServiceModel.Description; | |
using System.ServiceModel.Dispatcher; | |
using BBR.WebService.Shared.Infrastructure.BehaviorExtensions.Validation; | |
public sealed class CustomValidationOperationInvoker : CustomValidationOperationInvokerBase | |
{ | |
public CustomValidationOperationInvoker(OperationDescription operationDescription, DispatchOperation operation) | |
: base(operationDescription, operation) | |
{ | |
} | |
protected override bool Validate(string operationName, object[] inputs) | |
{ | |
// VALIDATION LOGIC GOES HERE | |
string value = inputs[0] as string; | |
if (value == "throw") | |
{ | |
throw new FaultException(string.Format("[{0}]: Invalid webservice request", operationName)); | |
} | |
//var authRequest = inputs[0] as AuthenticationRequestContract; | |
//if (authRequest != null) | |
//{ | |
// IKernel kernel = new StandardKernel(new MyServiceModule()); | |
// var service = kernel.Get<IMyDataBusService>(); | |
// var validationResult = service.ValidateUserWithToken(authRequest.Login, authRequest.Password); | |
// Trace.WriteLine("Is auth:" + validationResult); | |
//} | |
return true; | |
} | |
} | |
#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 sealed class CustomValidationOperationAttribute : CustomValidationOperationAttributeBase | |
{ | |
protected override CustomValidationOperationInvokerBase CreateInvoker(OperationDescription operationDescription, DispatchOperation dispatchOperation) | |
{ | |
return new CustomValidationOperationInvoker(operationDescription, dispatchOperation); | |
} | |
} | |
#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 sealed class CustomValidationServiceBehaviorAttribute : CustomValidationServiceBehaviorAttributeBase | |
{ | |
protected override CustomValidationOperationBehaviorBase CreateOperationBehavior() | |
{ | |
return new CustomValidationOperationBehavior(); | |
} | |
} | |
public sealed class CustomValidationOperationBehavior : CustomValidationOperationBehaviorBase | |
{ | |
public override CustomValidationOperationInvokerBase CreateInvoker(OperationDescription operationDescription, DispatchOperation operation) | |
{ | |
return new CustomValidationOperationInvoker(operationDescription, operation); | |
} | |
} | |
#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.Collections.ObjectModel; | |
using System.Diagnostics; | |
using System.ServiceModel; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Description; | |
using System.ServiceModel.Dispatcher; | |
public abstract class CustomValidationOperationInvokerBase : IOperationInvoker, IParameterInspector | |
{ | |
private readonly IOperationInvoker originalInvoker; | |
private readonly string operationName; | |
public CustomValidationOperationInvokerBase(OperationDescription operationDescription, DispatchOperation dispatchOperation) | |
{ | |
this.originalInvoker = dispatchOperation.Invoker; | |
this.operationName = dispatchOperation.Name; | |
} | |
#region IOperationBehavior Members | |
public object Invoke(object instance, object[] inputs, out object[] outputs) | |
{ | |
// TODO: Remove this when finished | |
#if DEBUG | |
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); | |
#endif | |
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) | |
{ | |
// REQUEST VALIDATION | |
this.Validate(operationName, inputs); | |
return null; | |
} | |
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) | |
{ | |
} | |
#endregion | |
protected abstract bool Validate(string operationName, object[] inputs); | |
} | |
#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 abstract class CustomValidationOperationAttributeBase : Attribute, IOperationBehavior | |
{ | |
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) | |
{ | |
var invoker = this.CreateInvoker(operationDescription, dispatchOperation); | |
dispatchOperation.Invoker = invoker; | |
dispatchOperation.ParameterInspectors.Add(invoker); | |
} | |
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) {} | |
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) {} | |
public void Validate(OperationDescription operationDescription) {} | |
protected abstract CustomValidationOperationInvokerBase CreateInvoker(OperationDescription operationDescription, DispatchOperation dispatchOperation); | |
} | |
#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 abstract class CustomValidationServiceBehaviorAttributeBase : Attribute, IServiceBehavior | |
{ | |
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) | |
{ | |
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints) | |
{ | |
foreach (OperationDescription operation in endpoint.Contract.Operations) | |
{ | |
IOperationBehavior behavior = this.CreateOperationBehavior(); | |
operation.Behaviors.Add(behavior); | |
} | |
} | |
} | |
public void AddBindingParameters( | |
ServiceDescription serviceDescription, | |
ServiceHostBase serviceHostBase, | |
Collection<ServiceEndpoint> endpoints, | |
BindingParameterCollection bindingParameters) | |
{ | |
} | |
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } | |
protected abstract CustomValidationOperationBehaviorBase CreateOperationBehavior(); | |
} | |
public abstract class CustomValidationOperationBehaviorBase : IOperationBehavior | |
{ | |
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) | |
{ | |
var invoker = this.CreateInvoker(operationDescription, dispatchOperation); | |
dispatchOperation.Invoker = invoker; | |
dispatchOperation.ParameterInspectors.Add(invoker); | |
} | |
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } | |
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } | |
public void Validate(OperationDescription operationDescription) { } | |
public abstract CustomValidationOperationInvokerBase CreateInvoker(OperationDescription operationDescription, DispatchOperation dispatchOperation); | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment