0

In my WebApiConfig.cs class for a .NET 4.6.1 WebApi project, I want to enable CORS only if an app setting in web.config is set to true. I generally read web.config AppSettings using an AppSettings class that converts the values from string to a more appropriate data type. I declare an IAppSettings interface and register the type with the Autofac DI container I'm using.

However, in this case, WebApiConfig is a static class, and its Register method is called as follows: GlobalConfiguration.Configure(WebApiConfig.Register); I can't change the signature of the GlobalConfiguration.Configure class, so I don't see how to inject the IAppSettings object to make it accessible in the Register method. Of course I can access ConfigurationManager, but that seems very hacky. Of course I could also declare AppSettings as a static class, but that would make unit testing difficult. Is there some cleaner way to do this?

Here's the relevant code - the ConfigurationManager line is the one I want to replace with a call to an appSettings class:

    public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        if (System.Configuration.ConfigurationManager.AppSettings.Get("IsCorsEnabled", false))
        {
            config.EnableCors();
        }
        // Web API routes
        config.MapHttpAttributeRoutes();

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

Many thanks for any assistance!!

2
  • Consider switching to ASP.Net Core, which solves all of these problems. Commented Jul 5, 2016 at 2:19
  • Thanks - I have been considering it, but am concerned that Entity Framework Core isn't fully mature - heard it doesn't support lazy loading yet? I tried .NET Core hosting, targeting .NET 4.6.1, but after 1.5 days still couldn't get a very basic solution with a WebApi project and a Data (EntityFramework) project working - can't seem to find any comprehensive guidance on how to set up the projects and reference them in that scenario - any links that make that straightforward would also certainly be welcome! Commented Jul 5, 2016 at 2:35

1 Answer 1

2

Say you have an interface like this for your appsettings (sort of):

public interface IAppSettings
{
    T Get<T>(string name);
}

And a default implementation of this which just wraps around ConfigurationManager:

public class DefaultAppSettings : IAppSettings
{
    public T Get<T>(string name)
    {
        return (T)Convert.ChangeType(ConfigurationManager.AppSettings[name], typeof(T));
    }
}

If you then define a class like this:

public static class CurrentAppSettings
{
    public static Func<IAppSettings> Instance = () => new DefaultAppSettings();
}

You could use this in your register method:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        if (CurrentAppSettings.Instance().Get<bool>("IsCorsEnabled"))
        {
            config.EnableCors();
        }
        // Web API routes
        config.MapHttpAttributeRoutes();

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

If you want to inject some other implementation of this, like in a test, you just set the CurrentAppSettings instance to something else:

[Test]
public void SomeTest()
{
    CurrentAppSettings.Instance = () => new SimpleKeyValueAppSettings(new Dictionary<string, string>());

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

1 Comment

Aah, that makes sense! Different approach, but that works, accomplishes everything I was hoping to accomplish. Thanks much!

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.