1

I'm currently stuck with a self-hosted Web API I'm trying to use within a unit test.

Whatever route I try, I get a 404 not found error. The issue is, when hosting the very same Web API within IIS, everything works fine. I'm guessing it's a simple typo/mistake in my test config, but I can't make it work, any help appreciated.

Here's the fully working config I used for my Web API when hosted within IIS:

public class WebApiApplication : System.Web.HttpApplication
{
    /// <summary>
    /// Entry point of the application.
    /// </summary>
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    }
}

public static void Register(HttpConfiguration config)
{
    // IoC configuration
    var container = new UnityContainer();
    UnityContainerConfigurator.Configure(container, new PerRequestLifetimeManager());

    // Set the dep resolver
    config.DependencyResolver = new UnityDependencyResolver(container);

    // Web API routes
    config.MapHttpAttributeRoutes();

    // Only supports JSON formatter
    config.Formatters.Clear();
    config.Formatters.Add(new JsonMediaTypeFormatter());
    config.Formatters.JsonFormatter.SerializerSettings = CustomJsonSerializerSettings.Create();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional });

    // Custom filter
    var providers = config.Services.GetFilterProviders().ToList();
    var defaultprovider = providers.Single(i => i is ActionDescriptorFilterProvider);
    config.Services.Remove(typeof(IFilterProvider), defaultprovider);
    config.Services.Add(typeof(IFilterProvider), new UnityFilterProvider(container));
}

Here's the non-working config I'm using for my unit test:

var config = new HttpSelfHostConfiguration(webApiURL);

#if DEBUG
    // For debug purposes
    config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
#endif

// Web API routes
config.MapHttpAttributeRoutes();

// Only supports JSON formatter
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings = CustomJsonSerializerSettings.Create();

config.Routes.MapHttpRoute(
      name: "DefaultApi",
      routeTemplate: "api/{controller}/{action}/{id}",
      defaults: new { id = RouteParameter.Optional });

// Custom filter
var providers = config.Services.GetFilterProviders().ToList();
var defaultprovider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
config.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new UnityFilterProvider(this.UnityContainer));

// Overwrites the IoC configuration
config.DependencyResolver = new UnityDependencyResolver(this.UnityContainer);

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

this.webApiServer = new HttpSelfHostServer(config);
this.webApiServer.OpenAsync().Wait();
enter code here

I also tried the new Owin hosting services, same result:

public class Startup
{
    private static IUnityContainer container;

    /// <summary>
    /// Overwrites the IoC configuration.
    /// </summary>
    /// <param name="container">The container.</param>
    public static void ConfigureIoC(IUnityContainer container)
    {
        Startup.container = container;
    }

    /// <summary>
    /// This code configures Web API. The Startup class is specified as a type
    /// parameter in the WebApp.Start method.
    /// </summary>
    /// <param name="appBuilder">The application builder.</param>
    public void Configuration(IAppBuilder appBuilder)
    {
        if (Startup.container == null)
        {
            throw new Exception("Call ConfigureIoC first");
        }

        // Configure Web API for self-host.
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
              name: "DefaultApi",
              routeTemplate: "api/{controller}/{action}/{id}",
              defaults: new { id = RouteParameter.Optional });

        // Web API routes
        config.MapHttpAttributeRoutes();

        // Only supports JSON formatter
        config.Formatters.Clear();
        config.Formatters.Add(new JsonMediaTypeFormatter());
        config.Formatters.JsonFormatter.SerializerSettings = CustomJsonSerializerSettings.Create();

        // Custom filter
        var providers = config.Services.GetFilterProviders().ToList();
        var defaultprovider = providers.Single(i => i is ActionDescriptorFilterProvider);
        config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
        config.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new UnityFilterProvider(container));

        // Overwrites the IoC configuration
        config.DependencyResolver = new UnityDependencyResolver(Startup.container);

        appBuilder.UseWebApi(config);
    }
}

The very same REST request I'm starting with Postman is a success when hosted within IIS, and a 404 when hosted within my unit test as a self hosted service.

Any hint?

4
  • The IIS Url contains a VirtualDirectory, have you tried to omit that for your self hosting application? Commented Sep 26, 2016 at 9:27
  • @MartinBrandl I did not omit that part, but after your comment I double-checked my webApiUrl variable (that is used as the base URL for the self hosted service),I found the value was incorrect... How dumb of me... Now I get a different "No route data was found for this request." error, at least the service is not responding 404 anymore. Commented Sep 26, 2016 at 9:41
  • Got it working! Basically the base URL provided to the self hosted service was wrong. I spent wayyy too much time figuring that out. You might want to add this as an answer @MartinBrandl so I can give you some kudos for the help Commented Sep 26, 2016 at 10:10
  • 1
    Good job - I added the answer even you figured it out yourself :-) Commented Sep 26, 2016 at 10:17

1 Answer 1

1

You should check whether your self hosting application contains a Virtual Directory (like IIS). And as you mentioned ensure the base path is valid.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.