Search code examples
c#castle-windsor

How to get HttpContext within Windsor per request


I am implementing an audit manager using Windsor Castle. However, I am unsure how to get the currently executing HttpContext per request. I need it to log certain information within the request such as I.P. address. If possible, can you also tell me if there's a safe & easy way to convert the return value to a JsonResult object, if it is that type?

public class ControllersInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Classes.FromThisAssembly()
            .BasedOn<IController>()
            // a new instance should be provided by Windsor every time it is needed
            .LifestyleTransient()
            .Configure(c => c.Interceptors(new InterceptorReference(typeof(ControllerInterceptor)))));
    }

    public class ControllerInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            try
            {
                string controller = invocation.TargetType.FullName;
                string method = invocation.Method.Name;
                List<string> parameters = new List<string>();

                for (int i = 0; i < invocation.Arguments.Length; i++)
                {
                    var param = invocation.Arguments[i];
                    parameters.Add(param.ToString());
                }

                invocation.Proceed();

                string result = JsonConvert.SerializeObject(invocation.ReturnValue ?? new object());

                var auditItem = new AuditItem
                {
                    ActionRequested = method,
                    Controller = controller,
                    Denied = false,
                };

            }
            catch (Exception ex)
            {
                _log.Error("ControllerInterceptor.Intercept:: " + ex.Message, ex);
            }
        }
    }

Solution

  • You can register a HttpContextBase with Castle Windsor and resolve it using a factory method. Use the PerWebRequest lifestyle to ensure it's scoped to each request.

    container.Register(
        Component.For<HttpContextBase>()
                 .UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current))
                 .LifestylePerWebRequest());