Configuration of asp.net core using settings - configuration

I'm evaluating asp.net core and .net core and I'm not yet sure about some things. In the past it was possible to configure many components using the web.config out of the box.
To name some examples:
There was the membership-provider and I could implement many providers but I was able ton configure later which provider should be used. This was dependend of the use-case. Now I should use asp.net identity - but I can only find configurations that are performed in sourcecode.
Same for authentication. I can define "CookieAuthentication" and have to set the name, loginpath or the timeout within sourcecode. In the past I was able to set timeout, etc... via web.config.
Is there any way to configure partially these things out of the box from a config-file? Or is this not supported anymore and I have to implement this configuration on my own? In the past this was a really comfortable way.

In ASP.NET Core, Web.config file is used ONLY for IIS configuration, you cannot use it for application configuration, but there are new, better, more flexible configuration options that you can use.
There are multiple configuration sources that you can use, but in this example I'm using json. These examples are from working code in my SimpleAuth project.
You can configure things in startup from configuration files.
First you add a config file in json format that maps to your class. You can see my example class here, and the json file it maps from here
builder.AddJsonFile("simpleauthsettings.json", optional: true);
Then, in the ConfigureServices method you configure your class to be wired up from the config system as shown
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
Then you add an IOptions accessor of your class to the method signature of the Configure method in the Startup.cs
The Dependency Injection will inject it into that method for you so you can use it there to configure things. Specifically I'm setting the cookie authentication scheme and name from my settings object.
The noteworthy part is that you can add whatever you want to the Configure method signature, and as long as it is something that has been registered in the ConfigureServices method, the DI will be able to inject it for you.
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
// this file is the custom configuration file to hydrate my settings from
builder.AddJsonFile("simpleauthsettings.json", optional: true);
....
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
....
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
....
}
// note that the DI can inject whatever you need into this method signature
// I added IOptions<SimpleAuthSettings> authSettingsAccessor to the method signature
// you can add anything you want as long as you register it in ConfigureServices
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IOptions<SimpleAuthSettings> authSettingsAccessor
)
{
...
// Add cookie-based authentication to the request pipeline
SimpleAuthSettings authSettings = authSettingsAccessor.Value;
var ApplicationCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = authSettings.AuthenticationScheme,
CookieName = authSettings.AuthenticationScheme,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
LoginPath = new PathString("/Login/Index"),
Events = new CookieAuthenticationEvents
{
//OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
}
};
app.UseCookieAuthentication(ApplicationCookie);
// authentication MUST be added before MVC
app.UseMvc();
}
}

Related

Startup.cs error (ASP.Net Core configuration)

I am trying to set up an ASP.Net Core application to read in configuration settings from a json file. I am using VS2015 and .NetCore 1.0 (with .Net Core Tools preview 2). I am having problems getting a simple piece of boiler plate code to compile.
I am using the following code, which was published at
http://asp.net-hacker.rocks/2016/03/21/configure-aspnetcore.html
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights
// pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
However, the IDE/compiler complains that 'the name "Configuration" does not exist in the current context' (last line of code). The only suggestion from the IDE is to include Microsoft.Extensions.Configuration. However this is a namespace which does not contain an object or property named "Configuration".
In addition 'AddApplicationInsightsSettings' fails with does IConfigurationBuilder not contain a definition for AddApplicationInsightsSettings and no extension method AddApplicationInsightsSettings accepting a first argument of type IConfigurationBuilder could be found
Any suggestions please ?
Thanks
Simply add Configuration property to your Startup class, tutorial has missed this 'step':
public IConfigurationRoot Configuration { get; set; }
ConfigurationBuilder.Build() method just returns instance of IConfigurationRoot, that you should save, if need to get settings further in Startup class (in ConfigureServices method for example).
Regarding second error, looks like you didn't add the Application Insights dependency:
{
"dependencies": {
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0"
}
}

Strategy for accessing an application-wide setting on the client in a .NET Core web app

We are in the process of re-writing one of our applications using ASP.NET Core. The architecture we're trying for has a Web API running on a different URL from the presentation. The root URL for this API will change in different environments, of course, so I'm trying to figure out how I can set up configuration and access to the Web API root URL in the JavaScript that requires it for retrieving data. For example, say I have an AJAX call to fetch some data from the API:
$.ajax({
dataType: "json",
url: "http://this.url.will.change/api/whatever", //this will change!
success: function(response) {
//load the items
}
});
I've set up appsettings.json files for various build/deploy scenarios and have them reading and injecting nicely, so I can store the URL there.
{
"Data": {
"DefaultConnection": {
"ConnectionString": "whatever"
}
},
"AppSettings": {
"ApiRootUrl": "http://apiroot/api/"
}
}
I considered writing a UrlHelper extension to provide the Web API root, but I don't think there's a way to inject the IOptions object into a static extension method. So, my question is really this: How can I make a configuration setting globally available in my CSHTML and JavaScript?
Update your Startup.cs like below
public class Startup {
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) {
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton(_ => Configuration);
}
}
Then on your controller you can inject configuration like this
public class ConfigurationController : Controller {
private readonly IConfigurationRoot config;
public ConfigurationController (IConfigurationRoot config) {
this.config = config;
}
public string Test() {
return config.Get<string>("AppSettings:ApiRootUrl");
}
}
We've used to create a special configuration controller which was responsible for creating a dynamic javascript file from selected configurations settings. You can inject IOptions to the controller. Then from the options you can construct a new custom configuration object which will hold only the properties you want to expose (you probably don't want to expose anything like connection string to your db).
Use a json library (like json.net) to serialize this custom configuration object to a JSON string and create file content out of it like
string fileContent = "var globalConf =" + JsonConvert.SerializeObject(configObject);
Convert the string to array of bytes and return it as FileContentResult.
We were also setting some cache headers so the browser didn't hit the controller each time and used cache.
Of course you need to setup routing o the call to specific URL will hit your controller and return the javascript file you have dynamically created. You can reference it on a website using usual script tag.
As for the server side rendering you can always include IOptions in the model (or create a new model which will wrap both options and the original model)

How to get data from settings json to mvc 6 view?

I want to load all settings key value pair from json file at once and use the settings key value in mvc 6 view page where required.I would be grateful if best solution is provided.I have a scenerio as below
if(Settings.enable_logo_text)
{
<span>Settings.logo_text</span>
}
The official documentation regarding the new configuration and options is quite good, I would recommend having a look there first.
Following the guidance provided there, start by creating a POCO class for your settings:
public class Settings
{
public string logo_text { get; set; }
public bool enable_logo_text { get; set; }
}
Update the ConfigureServices method of your startup class so you read your settings from the configured Configuration and is then available as a service that can be injected wherever you need to:
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<Settings>(Configuration);
services.AddOptions();
}
If you want to use a the appsettings.json file, make sure you also build your Configuration object including that json file. For example:
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
This way you can configure your values in the appsettings.json file and the values will be set on your Settings class:
{
...
"enable_logo_text": true,
"logo_text": "My Logo Text"
}
Finally, you can access the configured values by adding a IOptions<Settings> dependency. The most straightforward way would be to directly inject the options into the view (as explained in the docs), but you might want to consider injecting the options into the controller and passing them to the view in a more controlled way:
#inject IOptions<Settings> Settings
...
#if(Settings.Value.enable_logo_text)
{
<span>#Settings.Value.logo_text</span>
}

What has replaced ServiceResolver.GetFilterProviders() in ASP.NET WebAPI RC?

I have some code that's using a custom filter provider to perform property injection using Windsor on my action filters in a WebAPI project.
I'm just upgrading it from WebAPI beta to WebAPI RC, and I have a method in my container registration that used to read:
container.Register(
Component
.For<IEnumerable<IFilterProvider>>()
.UsingFactoryMethod(
() => GlobalConfiguration.Configuration.ServiceResolver.GetFilterProviders()
)
);
This would allow me to get the 'default' collection of filter providers and pass that into my custom filter provider, which would in turn retrieve the filters from each default provider, inject any missing dependencies via property injection, and return the filter with dependencies resolved.
In ASP.NET WebAPI RC, the ServiceResolver is now DependencyResolver and no longer has a GetFilterProviders() method - what should I be using in its place?
EDIT: Right, the following registration syntax is working - as in, it's passing all the unit tests and doesn't appear to be leaking memory or anything - but I'm not sure that explicitly binding to the instance returned by the Services.FilterProviders() is a good idea...
var filterProviders = GlobalConfiguration.Configuration.Services.GetFilterProviders();
container.Register(
Component.For<IEnumerable<IFilterProvider>>().Instance(filterProviders),
Component.For<IFilterProvider>().ImplementedBy<WindsorFilterProvider>()
);
and, for the sake of completeness, the WindsorFilterProvider looks like this:
public class WindsorFilterProvider : IFilterProvider {
private readonly IWindsorContainer container;
private readonly IEnumerable<IFilterProvider> filterProviders;
public WindsorFilterProvider(IWindsorContainer container, IEnumerable<IFilterProvider> filterProviders) {
this.container = container;
this.filterProviders = filterProviders;
}
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor) {
var filters = filterProviders.SelectMany(fp => fp.GetFilters(configuration, actionDescriptor)).ToList();
foreach (var filter in filters) container.Inject(filter.Instance);
return filters;
}
}
I guess the question is - is this a good way of doing this, or is there a recommended approach that I should be using instead?

OSGi Declarative Services and Config Admin

I'm writting bundle with declarative services usage. For configuration I'm using properties in DS declaration. Those props can be normally changed by Config Admin, but they are not persisted. After container restart, component has default values.
I'am using Config admin like this:
Configuration c = configurationAdmin.getConfiguration(UserAgent.SERVICE_PID, null);
System.out.println(c.getProperties()); // every time is null!
Dictionary props = new Hashtable();
props.put(UserAgent.PROPERTY_PORT, 5555);
c.update(props);
and in component I have:
// ...
#Modified
public void updated(ComponentContext context) {
config = context.getProperties();
init();
}
#Activate
protected void activate(ComponentContext context) {
config = context.getProperties();
init();
}
//...
I'm using Felix, properties file is stored in cache
service.bundleLocation="file:bundles/cz.b2m.osgi.phonus.core_1.0.0.SNAPSHOT.jar"
service.pid="cz.b2m.osgi.phonus.sip"
port=I"5555"
But after restart isn't loaded. What I'm doing wrong? Thanks for all tips.
Problem was in Pax Runner which every restart (clean) erased the data folder of Config Admin bundle.
To make sure that Pax Runner does not clear the data, you can use the --usePersistedState=true flag.