Skip to content

Instantly share code, notes, and snippets.

@robashton
Created February 9, 2011 16:58
Show Gist options
  • Save robashton/818803 to your computer and use it in GitHub Desktop.
Save robashton/818803 to your computer and use it in GitHub Desktop.
A botched attempt at injecting a validation step to the behaviour onion
public class ServiceActionCall : ActionCall
{
private readonly ActionCall inner;
public ServiceActionCall(ActionCall inner) : base(inner.HandlerType, inner.Method)
{
this.inner = inner;
}
protected override ObjectDef buildObjectDef()
{
var originalDef = base.buildObjectDef();
originalDef.Type = typeof (ValidationAwareActionInvoker<,>).MakeGenericType(inner.HandlerType,
inner.Method.ReturnType);
return originalDef;
}
public override BehaviorCategory Category
{
get { return BehaviorCategory.Call; }
}
}
public class ServiceInvocationConvention : IConfigurationAction
{
public void Configure(BehaviorGraph graph)
{
graph.Actions().Where(x => x.HandlerType.Name.EndsWith("CommandHandler"))
.Each(x =>
{
var validationType = typeof (ServiceValidationBehaviour<>).MakeGenericType(x.InputType());
x.WrapWith(validationType);
var defaultInvoker = x.OfType<ActionCall>().FirstOrDefault();
defaultInvoker.ReplaceWith(new ServiceActionCall(defaultInvoker));
var jsonBehaviourType = typeof(ServiceOutputRenderBehaviour<>).MakeGenericType(typeof(ServiceCommandOutput));
var outputNode = new OutputNode(jsonBehaviourType);
x.AddToEnd(outputNode);
graph.Observer.RecordCallStatus(x,"Wiring up services to always return JSON");
});
}
}
public class ServiceValidationBehaviour<T> : IActionBehavior where T : class
{
private readonly IFubuRequest fubuRequest;
private readonly IValidator<T> validator;
public IActionBehavior InsideBehavior { get; set; }
public ServiceValidationBehaviour(IFubuRequest fubuRequest, IValidator<T> validator)
{
this.fubuRequest = fubuRequest;
this.validator = validator;
}
public void Invoke()
{
var results = validator.Validate(fubuRequest.Get<T>());
var output = new ServiceCommandOutput()
{
Success = results.IsValid,
Messages = results.Errors
.Select(error=> new ServiceCommandOutputMessage()
{
Key = error.PropertyName,
Text = error.ErrorMessage
}).ToArray()
};
fubuRequest.Set(output);
if (InsideBehavior != null)
{
this.InsideBehavior.Invoke();
}
}
public void InvokePartial()
{
this.Invoke();
}
}
public class ValidationAwareActionInvoker<TController, TInput> : OneInZeroOutActionInvoker<TController, TInput> where TInput : class
{
private readonly IFubuRequest request;
public ValidationAwareActionInvoker(IFubuRequest request, TController controller, Action<TController, TInput> action) : base(request, controller, action)
{
this.request = request;
}
protected override FubuMVC.Core.DoNext performInvoke()
{
var result = request.Get<ServiceCommandOutput>();
if (result.Success)
{
base.performInvoke();
}
return FubuMVC.Core.DoNext.Continue;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment