0

This is kind of duplicate of this but the solution has used DependencyResolver from MVC, while I am working with ASP.NEt web forms.

So how can we do the same in web form for unity 3

Community
  • 1
  • 1
dkt
  • 144
  • 2
  • 13

1 Answers1

0

It seems to me that we will have to have another Composition Root for the Http Handler(s). I am saying "another" because your first Composition Root is for your ASP.NET web forms application.

Usually, a single application should only have a single Composition Root. However, framework restrictions sometimes force us to have multiple ones.

We will create a new Composition Root by having our own Http Handler Factory. I.e., a class that implements IHttpHandlerFactory.

Consider this example. You have the following service and a handler that depends on it (via constructor injection):

public interface IService
{
    string GetSomething();
}

public class Service : IService
{
    public string GetSomething()
    {
        return "Something nice";
    }
}

public class MyHandler : IHttpHandler
{
    private readonly IService m_Service;

    public MyHandler(IService service)
    {
        m_Service = service;
    }

    public void ProcessRequest(HttpContext context)
    {
        HttpRequest request = context.Request;
        HttpResponse response = context.Response;

        response.Write("<html>");
        response.Write("<body>");
        response.Write(string.Format("From handler 1: <h2>{0}</h2>", m_Service.GetSomething()));
        response.Write("</body>");
        response.Write("</html>");
    }

    public bool IsReusable { get; private set; }
}

We will create the following handler factory:

public class HandlerFactory : IHttpHandlerFactory
{
    private readonly UnityContainer m_Container;

    public HandlerFactory()
    {
        m_Container = new UnityContainer();
        m_Container.RegisterType<IService, Service>();
    }

    public IHttpHandler GetHandler(HttpContext context, string request_type, string url, string path_translated)
    {
        if (url.EndsWith(".ext1"))
            return m_Container.Resolve<MyHandler>();

        //Here for other cases, we can resolve other handlers

        return null;
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
        //Here we should use the container to release the handler. However, unity seems to be missing this feature
    }
}

This handler acts as a Composition Root. When it receives a request to create an handler, based on some logic (which in my case is based on the request file extension), it creates the appropriate handler. You can have your own logic here.

To tell the ASP.NET framework about the factory, we need to register the handler in web.config like this:

<system.webServer>
  <handlers>
    <add name="HandlerFactory" verb="*" path="Custom/*" type="WebApplication1.HandlerFactory" />
  </handlers>
</system.webServer>

Where WebApplication1 is the namespace where the factory exists.

I am using Custom/* as the path. This means that any request in the format /Custom/* will be served using the factory. You can have your own path here.

Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
  • Ok, what if we are creating rest api using handlers, there will be many handlers and there paths needs to be defined in the web.config. How can we extend this. and `//Here for other cases, we can resolve other handlers` in your example seems odd for my case, I did using following code ` var instance = BuildManager.CreateInstanceFromVirtualPath(url, typeof(IHttpHandler)); return Container.Resolve(instance.GetType(), null) as IHttpHandler;` – dkt Oct 18 '15 at 11:07
  • One way to do that would be do define some custom application settings in web.config (i.e. appSettings) that will contain information for each handler. For example, you can put for each handler an app setting that has the handler name as key and the path (or some criteria) as value. Then in your factory, you can read such data and determine which handler to use. – Yacoub Massad Oct 18 '15 at 11:17