OWIN Startup类与WebAPIConfig.Register方法一起执行

时间:2018-10-05 23:19:38

标签: c# asp.net-web-api integration-testing owin self-hosting

我在集成测试项目之一中使用Microsoft.Owin.Hosting自托管Web API,以测试端到端功能。

[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
        }
    }
}

我能够自行托管Web API并能够调用控制器操作。 Owin需要一些Startup类配置,如下所示:

[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);
        }
    }
}

这是我的Web API Config方法,如下所示:

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 }
        );            
    }
}

问题

  • 运行主应用程序(而不是测试项目)时,会同时调用Owin启动和Web API配置方法。
  • 如果我要配置一些服务或过滤器,它将被调用两次。
  • 我以为如果我正在运行测试项目,它应该仅调用owin启动文件(它现在正在执行),而当我调试主应用程序时,它应该仅调用Web API配置注册方法。

有人知道这是应该起作用的方式还是我做错了什么?

2 个答案:

答案 0 :(得分:3)

首先,系统需要一种方法来区分环境。

<appSettings>
    <add key="APP_ENVIRONMENT" value="Development" />
    <!-- ... -->
</appSettings>

由于在生产环境中运行Owin启动和Web api配置方法时,都已将OWIN配置为项目中的头等公民。

我建议将代码从Application_Start移至owin启动

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start() {
        //REMOVE THIS AND LET OWIN STARTUP HANDLE SETUP
        //GlobalConfiguration.Configure(WebApiConfig.Register);
    }
}

,以便仅根据配置的环境调用一次。

[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);
            }
        }
    }
}

请注意WebApiConfig.Register的重用,以避免重复代码。如果要实施其他配置(例如,开发,测试,登台,起诉...等),则相同的配置将应用于两种环境,并且都在同一位置。

测试项目app.config将包含当前环境的设置

<appSettings>
    <add key="APP_ENVIRONMENT" value="Test" />
    <!-- ... -->
</appSettings>

并调用用于自我托管的启动配置,否则它将默认返回到生产设置,但也已经在web.config

中进行了配置
<appSettings>
    <add key="APP_ENVIRONMENT" value="Production" />
    <!-- ... -->
</appSettings>

答案 1 :(得分:1)

您需要在通过OWIN pipeline初始化Web api或使用Application_Start中的旧方法之间进行选择,请参见the application lifecycle

如果您保留Application_StartOwinSartup,则您的网络api将初始化两次