Missing HttpHostConfiguration / IResourceFactory in 0.5.0

Topics: Web Api
Sep 17, 2011 at 1:33 AM

Hi everyone,

 

Still battling here with the new build :-) Any help really appreciated.

 

I am using a custom HttpHostConfiguration to inject Unity dependencies, but its now failing... Also it appears that IResourceFactory doesn't exist?

 

Microsoft.ApplicationServer.Http  and Microsoft.ApplkicationServer.HttpEnhancements seems to be the issue.  I have 0.3.0 of these files and the HostConfiguration and IResourceFactory are there..

 

here is how i am using it

 

  var hostConfig = HttpHostConfiguration.Create();
 
            //hostConfig.AddMessageHandlers(typeof(ApiKeyVerificationChannel));
            hostConfig.SetResourceFactory(new AuthenticationsResourceFactory());
            hostConfig.Configuration.UseNewtonsoftJson();

and all my resource factory classes implement IResourceFactory like so


namespace MyService.Rest.Resources
{
    using System;
    using System.Net.Http;
    using System.ServiceModel;
 
    using Microsoft.ApplicationServer.Http.Description;
    using Microsoft.Practices.Unity;
 
    public class UsersResourceFactory : IResourceFactory
    {
        public object GetInstance(Type serviceType, InstanceContext instanceContext, HttpRequestMessage request)
        {
            return DependencyInjection.Container.Resolve<ISecurityResource>();
        }
 
        public void ReleaseInstance(InstanceContext instanceContext, object service)
        {
         //   throw new NotImplementedException();
        }
    }  
}




The errors i am getting are

Error    16    The type or namespace name 'HttpHostConfiguration' could not be found (are you missing a using directive or an assembly reference?) 

Error    3    The type or namespace name 'IResourceFactory' could not be found (are you missing a using directive or an assembly reference?)  
Sep 17, 2011 at 10:56 AM
Edited Sep 17, 2011 at 11:05 AM

Yes I ResourceFactory is no longer needed.

Here is how I am registering routes:

/////////////////////////////////////////////////////////////////
// api
webApiConfig = new WebApiConfiguration()
{
   EnableTestClient = false,
   MessageHandlerFactory = () => new DelegatingHandler[]{IocFactory.GetInstance<AuthenticationMessageHandler>()},
    CreateInstance = (serviceType, context, request) => IocFactory.GetInstance(serviceType),
   ErrorHandlers = (errorHandlers, serviceEndpoint, operationDescriptions) =>{
     errorHandlers.Add(IocFactory.GetInstance<BadRequestErrorHandler>());
        }
 };
webApiConfig.UseJsonNet();
routes.MapServiceRoute<AchievementWcfService>("api/achievement", webApiConfig);
 

As you see I am using IocFactory to construct message handlers, error handlers and the ServiceContracts (CreateInstance) themselves.

IocFactory is just a thin wrapper around Structure Map. You can use your own Ioc framework,

but that should give you an idea of how to set them up.

 

       public static class IocFactory
    {
        //
        // Summary:
        //     Creates or finds the default instance of type T
        //
        // Type parameters:
        //   PLUGINTYPE:
        public static PLUGINTYPE GetInstance<PLUGINTYPE>()
        {
            return ObjectFactory.GetInstance<PLUGINTYPE>();
        }

        public static object GetInstance(Type pluginType)
        {
            return ObjectFactory.GetInstance(pluginType);
        }
    }
Sep 21, 2011 at 1:42 PM

Hi John,

Did you get this working?  I've slammed right up against this problem myself  :(

I'm hosting in an MVC3 application and my configuration was as follows:

    protected void Application_Start()
    {
      AreaRegistration.RegisterAllAreas();

      var container = InstantiateUnityContainer();
      var config = HttpHostConfiguration.Create()
        .AddMessageHandlers(typeof(UriFormatExtensionMessageChannel))
        .AddResponseHandlers(c => c.Add(new JsonpResponseHandler()), (s, o) => true)
        .SetResourceFactory(new UnityResourceFactory(container));

      SetMappings();

      RouteTable.Routes.MapServiceRoute<Resources.PayloadResource>("Payload", config);
      RouteTable.Routes.MapServiceRoute<Resources.SearchResource>("Search", config);
      RouteTable.Routes.MapServiceRoute<Resources.PayloadContentTypeResource>("ContentTypes", config);

      RegisterGlobalFilters(GlobalFilters.Filters);
      RegisterRoutes(RouteTable.Routes);

      AutomapperBootstrapper.ConfigureAutomapper();

    }

    public void SetMappings()
    {
      var mappings = new List<UriExtensionMapping>();
      mappings.AddMapping("xml", "application/xml");
      mappings.AddMapping("json", "application/json");

      this.SetUriExtensionMappings(mappings);
    }

But obviously all this seems to have changed and I'm lost again...

Sep 21, 2011 at 1:47 PM

Hi yes i did.

 

The solution posted by SantiagoIT works great. I had slightly modify it for use with Unity ... but works great..

 

Here is a quick example of a resource

 

           // NotificationsResource
            webApiConfig = new WebApiConfiguration()
            {
                EnableTestClient = false,
                CreateInstance = (serviceType, context, request) => DependencyInjection.Container.Resolve<INotificationsResource>(),
                MessageHandlerFactory = () => new DelegatingHandler[] { new ApiKeyVerificationChannel() },
            };
 
            webApiConfig.UseNewtonsoftJson();
 
            RouteTable.Routes.MapServiceRoute<NotificationsResource>("notifications", webApiConfig);



I also had to update the NewtonSoftJson extension method but it was pretty easy.. heres what changed

 public static class HttpHostConfigurationExtensions
    {
        public static void UseNewtonsoftJson(this HttpConfiguration config)
        {


Sep 21, 2011 at 2:24 PM

Wow, thanks for the quick reply.

I was trying to adapt the MEF configuration stuff in the advanced sample, as I did with Preview 4, but not being familiar with MEF I'm struggling to make sense of it.  :(

Cheers,
Nick

 

Sep 21, 2011 at 5:32 PM

Ok, I'm obviously missing something here and I've been staring at it so long my brain is starting to haemorrhage out of my eyes.

Two questions if I may?

1. Do I have to repeat this config for each resource class I have? There are only 3 at the moment but that will only increase given time.

2. What is the ApiKeyVerificationChannel class you are using?

Apologies for the stupid questions.

Nick.

Coordinator
Sep 21, 2011 at 7:50 PM

Hi Nick,

We updated the advanced contact manager sample to use the new model. Take a look at the updated code and let us know if you still need help wiring up MEF.

public class Global : System.Web.HttpApplication

{

protected void Application_Start(object sender, EventArgs e)

{

// use MEF for providing instances

var catalog = new AssemblyCatalog(typeof(Global).Assembly);

var container = new CompositionContainer(catalog);

var config = new MefConfiguration(container);

config.EnableTestClient = true;

RouteTable.Routes.SetDefaultHttpConfiguration(config);

//remove support for OData json

var odataFormatter = new ODataMediaTypeFormatter();

odataFormatter.SupportedMediaTypes.Clear();

odataFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/atom+xml"));

config.Formatters.AddRange(

odataFormatter,

new ContactPngFormatter(),

new VCardFormatter(),

new CalendarFormatter());

config.MessageHandlerFactory = () => container.GetExportedValues<DelegatingHandler>();

RouteTable.Routes.MapServiceRoute<ContactApi>("Contact");

RouteTable.Routes.MapServiceRoute<ContactsApi>("Contacts");

}

}

And as you can see above don’t have to repeat your config – the enhancements package allows you to register a global default configuration for the application.

Daniel Roth

From: GoldenHornet [email removed]
Sent: Wednesday, September 21, 2011 9:33 AM
To: Daniel Roth
Subject: Re: Missing HttpHostConfiguration / IResourceFactory in 0.5.0 [wcf:272903]

From: GoldenHornet

Ok, I'm obviously missing something here and I've been staring at it so long my brain is starting to haemorrhage out of my eyes.

Two questions if I may?

1. Do I have to repeat this config for each resource class I have? There are only 3 at the moment but that will only increase given time.

2. What is the ApiKeyVerificationChannel class you are using?

Apologies for the stupid questions.

Nick.

Coordinator
Sep 21, 2011 at 11:09 PM
Edited Sep 21, 2011 at 11:09 PM

1. You do not have to repeat the config. You can either pass the same config instances over an over in MapServiceRoute, or you can use the SetDefaultConfiguration method which is an extension method exposed off of the route collection.

2. The ApiKeyVerificationChannel is a sample that shows how to use api keys to validate requests. The code has not yet been updated to preview 5, but it is available for preview 4 on my skydrive here, choose ApiKeyVerification.  I "think" webapicontrib may have this updated for preview 5.

Sep 22, 2011 at 7:16 AM

Daniel, thanks for responding.

I guess I wasn't that clear, it was the end of a long day....  I'm trying to wire everything up using Unity and I am having trouble converting the MEF sample from ContactManager_Advanced into using Unity instead.

What I'm really trying to do is translate this bit into Unity-speak

var catalog = new AssemblyCatalog(typeof(Global).Assembly);

var container = new CompositionContainer(catalog);

var config = new MefConfiguration(container);


Glen, the reason for my question about repeating was from John's example where he was specifically resolving a single interface in setting up his WebApiConfiguration class. 

CreateInstance = (serviceType, context, request) => DependencyInjection.Container.Resolve<INotificationsResource>()

Coordinator
Sep 22, 2011 at 8:18 AM
Edited Sep 22, 2011 at 8:23 AM

GoldenHornet

For unity you would just do something like this

 

var container = new UnityContainer();
//configure unity
var config = new UnityConfiguration(container)

//within UnityConfiguration's constructor
CreateInstance = (s, c, r) => container.Resolve(s);

 

Aaah now I see what you mean. The design is not to hardcode the type you are resolving, but rather pass in whatever type you receive in the delegate (s in my example). This is to enable a single config to be used by all your routes. Also it enables the config class to be reused across applications (which was the goal)

@madridjohn, don't hardcode the type :-)

Sep 22, 2011 at 11:05 AM

Sweet, I'm back up and running again, thanks Glenn.

One last thing, I was using Alex Zeiter's JSONP example to enable cross-domain AJAX calls and the following line allowed me to add the ResponseHandler to the HttpHostConfiguration

.AddResponseHandlers(c => c.Add(new JsonpResponseHandler()), (s, o) => true)

Is it fairly straightforward to do this in the new WebApiConfiguration?  Do I still need to handle JSONP like this?

Sorry to keep bugging you...