Skip to main content

CastleWindsor issue with MVC Area

I have been stuck with this issue and couldn't take it out of my head. Hence, ended up putting in some heavy hours solving it. But hopefully it is worth it.

THE CONTEXT:

I am implementing a MVC solution for an existing Sitecore 8.0 implementation which uses Castle Windsor for it's dependency resolver. Let's say a a tiny microsite. I had to implement a SPEAK app as per one of the requirements. Below are the 2 most important things behind why I ran into this issue in the first place:

I needed to call a WebApi from my SPEAK app.
2. I decided to take MVC Area approach for my "tiny microsite" on a completely different sets of dlls

For example the dlls for my "tiny microsite" are MyTinyApp.Web.dll, MyTinyApp.Business.dll whereas the main website's dlls are BigWebsite.Web.dll, BigWebsite.Business.dll etc. 


WHY MVC AREA:

The reason I took the MVC Area approach was to completely separate my "tiny microsite" so that I don't have to touch any of the code from "BigWebsite" implementation (Or it can also be that the code base for the "Big Website" was unavailable to me .. imagine whatever floats your boat).


THE PROBLEM:

After I implemented my MVC Area project on dll called "MyTinyApp.Web.dll" for my "tiny microsite) upon trying to call the WebApi I started getting bellow error:



From the error it's clear that the routing got resolved without any issue. But Castle Windsor for some weird reason decided to step in like "hai .. new controller .. i need to resolve this" which I would be cool with until it couldn't and threw the bizarre error that doen't make sense to begin with. 

I have never told Castle Windsor to resolve any of my stuff for "MyTinyApp.Web.dll" and the exception was getting thrown from BigWebsite.Web.dll. 

WEIRD.


THE SOLUTION:

1. Create a processor in one of your project specific config file like below:


<pipelines>
      <initialize>
                               <processor patch:before="processor[@type='Sitecore.Mvc.Pipelines.Loader.InitializeGlobalFilters, Sitecore.Mvc']" type="MyTinyApp.CastleWindsor.Pipelines.Initialize.InitializeWindsorControllerFactory, MyTinyApp.CastleWindsor" />
     </initialize>

 </pipelines>

2. Create a settings to get the assembly name associated with Big Website's dependency resolver.

  <setting name="BigWebsiteDependancyResolverAssembly" value="BigWebsite.Web.DependencyResolution.ContainerManager,BigWebsite.Web" />

3. Implement the ControllerFactory for TinyApp:


public class InitializeWindsorControllerFactory
    {
        public virtual void Process(PipelineArgs args)
        {
            string assemblyAndClass = ConfigHelper.GetValue("BigWebsiteDependancyResolverAssembly");
                Type resolverType = Type.GetType(assemblyAndClass);
                IWindsorContainer icontainer = (IWindsorContainer)(resolverType.GetProperty("Container").GetValue(null));

                icontainer.Register(Classes.FromAssemblyNamed("oblog.client.mvc").BasedOn<IController>().LifestyleTransient());
        }

    }

And waalaaa .. Double Rainbow and Unicorn,



The trick here was to get it through reflection.

Thus I do not have to touch the BigWebsite codebase at all so I can avoid deployment headache for it. Resolving though reflection makes it completely independent to any other dlls.  

"This is mainly intended for future me." but seriously CastleWindsor WTF !!!!



UPDATE:



So one of my genius colleagues figured out that original implementation of ControllerFactory in BigWebsite.Web project(csproj) had flaw in it. 

Here's his post:


So it was originally like below:

public class WindsorControllerFactory : DefaultControllerFactory
    {
        private readonly IKernel kernel;

        public WindsorControllerFactory(IKernel kernel)
        {
            this.kernel = kernel;
        }

        public override void ReleaseController(IController controller)
        {
            kernel.ReleaseComponent(controller);
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
            }

            return (IController)kernel.Resolve(controllerType);
        }

    }

Because of this line in the implementation of the ContainerManager class which you put in the initialize pipeline:
container.Install(FromAssembly.InDirectory(new AssemblyFilter(Path.GetDirectoryName(Uri.UnescapeDataString((new UriBuilder(Assembly.GetExecutingAssembly().CodeBase)).Path)), "BigWebsite*.dll")));
the described error was getting thrown from this line :  
return (IController)kernel.Resolve(controllerType);

Weirdly, most of the blog/tutorials show this example for implementing Castle Windsor for MVC.
The fix is to have this instead:
try
            {
                return (IController)kernel.Resolve(controllerType);
            }
            catch (Exception ex)
            {
                // do something
                return base.GetControllerInstance(requestContext, controllerType);

            }

And everything else works fine from here. No need to implement extra pipeline to inject you "mvc area" implementation dll into the pipeline or modify existing implementation.


Hope it helps someone facing the same issue save time so that he/she can utilize it properly to dress up like wookie.

  



Comments

Popular posts from this blog

Smart wifi controlled irrigation system using Sonoff and Home Assistant on Raspberry Pi - Part 1

If you have a backyard just for the sake of having one or it came with the house and you hate watering your garden or lawn/backyard then you have come to the right place. I genuinely believe that it is a waste of my valuable time. I would rather watch bachelorette on TV than go outside, turn on tap, hold garden hose in hand to water. Too much work!! Luckily, we have things like sprinkler system, soaker etc which makes things a bit easy. But you still have to get off that comfy couch and turn on tap (then turn off if there's no tap timer in place). ** Skip to the youtube video part if reading is not your thing   When I first moved into my house at first it was exciting to get a backyard (decent size), but soon that turned on annoyance when it came down maintaining it, specially the watering part. I laid bunch sprinklers and soaker through out the yard and bought tap timer but I still needed to routinely turn on the tap timer. Eventually few days ago I had enough of this rub...

The story of a Hack Job

"So, you have hacked it" -- Few days ago one of the guys at work passed me this comment on a random discussion about something I built. I paused for a moment and pondered: Do I reply defending how that's not a hack. OR Do I just not bother I picked the second option for 2 reasons: It was late. It probably isn't worth defending the "hack vs" topic as the comment passed was out of context. So I chose the next best action and replied "Yep, sure did and it is working great.". I felt like Batman in the moment. In this post I will rant about the knowledge gap around hacking and then describe about one of the components of my home automation project (really, this is the main reason for this post) and use that as an example how hacking is cool and does not always mean bad. But first lets align on my definition of hacking: People use this term in good and bad, both ways. For example: "He/she did a hack job" -- Yeah, that probably...

Kubectl using SSH tunnel for TKG K8s Clusters

We know SSH'ing and probably many knows about SSH tunnel. The way, in my opinion, these 2 (SSH and SSH tunnel) are different to me (and I am in favor of SSH Tunnel) is how I use it. From tooling perspective I would almost always do tunnel instead of direct ssh.  In this post I will describe how to do SSH tunnel for kubectl to interact with remote kubernetes cluster (Specifically Tanzu Kubernetes Grid aka TKG cluster). Get the project ready to go from my github:  https://github.com/alinahid477/vsphere-with-tanzu-wizard Topics Backstory SSH tunnel for TKG Clusters using Docker container Technical stuff: Tunnel through Bastion for TKG K8s cluster Technical stuff: SSH Tunnel for Kubectl for remote K8s Clusters (same with or without docker) Technical stuff: Explain me this A famous quote from Darth Vader himself: "Feel the power of SSH Tunnel" Backstory Why ssh or ssh tunnel? The below diagram shows in what scenario a SSH or SSH Tunnel almost becomes a necessity. Let's st...

Understanding The Ingress and The Mesh components of Service Mesh

I wrote about the key concepts about service mesh and how to evaluate the requirements for a service mesh in my previous post here:  Deciphering the hype of Service Mesh . This post is a follow up from there covering the technical aspects. Part 1:   Deciphering the hype of Service Mesh Part 2:   Understanding The Ingress and The Mesh components of Service Mesh. Part 3: Uderstanding the observability component of Service Mesh (TBD in another post).  Almost all popular service mesh technologies/tools (eg: Istio, LinkerD) have both ingress and mesh capabilities. Conceptually, I see them as 2 mutually exclusive domain (integrated nicely by the underlying tool). Understanding  the ingress  and  the mesh  components individually, such as what they offer, what I can do with them etc, was the basic building block to my understanding of service mesh technology as a whole. This is arguably the most mis-represented topic in the internet. So, I thought,...

Customising Sitecore's Rich Text Editor. R u Kidding me?

theProblem: The front end ( html and css ) is set up such a way that for the description text form a sitecore content needs to have a <p> tag wrapped around it.  Now, I'm sure just by reading the above 2 lines you are thinking "WOW that's really simple and every RTE does that by default. So, continuing to reading this is useless and this guy is clearly dumb enough." "sayth whath" - said thor Well Yes and No. This is what I found: So by default the RTE wraps texts in a <p> tag =  TRUE.  BUT the catch is you will need to hit a enter or copy paste multiple paragraph. Then the RTE will clean the HTML and in the process it will wrap each para in a <p> tag. NICE. Of course there's a setting for it that you can modify and instead of <p> you can have <br/> and so. <setting name="HtmlEditor.LineBreak" value="p" /> And no you can't have anything that you want there.. there's a limit...

Do I like Drupal ?

Caution: The title might be somewhat misleading but kind of relevant. For the next few para I’m going to rant about drupal. (so all the drupal lovers please dont read beyond this point. Also this is my personal biased POV. I don’t gain or loose anything for or against drupal). Being said that : Here it goes: Do I like Drupal:  Hell No (so far) Why ? 1.  It’s shit. I think it’s an abomination of anything called CMS.  2.  It’s a VB (visula basic) in PHP. And as a developer I’ve never liked visual basic. And drupal is similar in extra that it is in PHP. So yes .. figure the rest out. 3.  It works well for the people who think “installing/upgrading their mobile OS makes them like developers hence Mr. KnowItAll.”. Guess what ? it doesn’t and that’s not what developers do. So, you installed few modules in drupal and made it work for the purpose - this doesnt qualify you as a developer nor makes drupal *really easy and nice CMS*. Eventually this *install ...