I am using Microsoft.Owin.Hosting
in my one of integration test project to self-host the Web API in order to test end to end functionality.
[TestMethod]
public void GetLoanApplications()
{
using (WebApp.Start<Startup>(url: url))
{
using (var client = new HttpClient())
{
// Create httpclient and send request-and-response-metadata-in-aspnet-web-api
}
}
}
I am able to self-host the web API and able to invoke the controller action. Owin requires some Startup
class configuration, which is as follows:
[assembly: OwinStartup(typeof(MyService.App_Start.Startup))]
namespace MyService.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
}
}
}
Here is my Web API Config method looks like:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Problem
Any idea on is this the way it should work or I am doing something wrong?
First the system would need a way to differentiate between the environments.
<appSettings>
<add key="APP_ENVIRONMENT" value="Development" />
<!-- ... -->
</appSettings>
Since when run in production both the Owin startup and web api config methods are getting called then OWIN is already configured as a first class citizen in the project.
I suggest moving the code from Application_Start
into owin start up
public class WebApiApplication : System.Web.HttpApplication {
protected void Application_Start() {
//REMOVE THIS AND LET OWIN STARTUP HANDLE SETUP
//GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
so that it is only invoked once depending on the configured environment.
[assembly: OwinStartup(typeof(MyService.App_Start.Startup))]
namespace MyService.App_Start {
public class Startup {
const string EnvironmentKey = "APP_ENVIRONMENT";
const string PRODUCTION = "Production";
const string TEST = "Test";
public void Configuration(IAppBuilder app) {
string ENVIRONMENT = ConfigurationManager.AppSettings[EnvironmentKey]
?? Production;
if(ENVIRONMENT == TEST) {
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
} else {
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
}
}
Note the reuse of the WebApiConfig.Register
to avoid repeated code. The same configuration will be applied for either environment and all in the same place if additional configurations were to be implemented (ie Development, Testing, Staging, Procustion...etc)
The test project app.config
would include the current environment's setting
<appSettings>
<add key="APP_ENVIRONMENT" value="Test" />
<!-- ... -->
</appSettings>
and invoke the start up configuration for self-hosting otherwise it will default back to production settings, but would have also been configured in the web.config
<appSettings>
<add key="APP_ENVIRONMENT" value="Production" />
<!-- ... -->
</appSettings>