IIS Change WebApi ConnectionString - asp.net-web-api

we are using webApi for one of our newest products which is hosted on IIS7.5 and written in ASP.NET5 (.Net Core).
In earlier web-applications it was possible to change the connectionstring in the web.config in windows-Explorer and the website running on IIS used the ConnectionString in the web.config file.
Is this still possible for modern WebAPIs (I have the ConnectionString insite appsettings.json)? I did not find a solution for that inside IIS or File-Explorer and using Environment-Variables do not fit our needs.
We need to switch between several DB-Instances so a very light file-based solution would be very welcome.
PS: We are using EntityFrameworkCore (aka EF7) Database-First as it is a new tool that is on top of our current database.

You can use one of configuration sources (including JSON, accessed by AddJsonFile() in the package Microsoft.Extensions.Configuration.Json) to read the settings file and then use values read from there to configure EF.
Example code could look like this:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
For more information see Configuration in ASP.NET Core docs or this answer.

Related

Asp.Net Web Api Logging

I want to setup logging on my asp.net web api (Not Asp.Net Core), and want to make sure that I follow best practices (as close as possible). I am using SeriLog in my services, and would like to use this product for my Web Api as well. I am not sure of the best way to setup logging in Web API, and I would like to set it up such that depending on the context (my api serves multiple apps) I would like to be able to log to a separate Microsoft Sql Server. Can somebody please provide some direction on how to get started at this task, potential pitfalls, or a link to an article that I have yet to find on how to set this up in Asp.Net?
You can create a centralized logger project and add serilog packages to this project only, and reference this project where you need to use serilog (your services).
And configure serilog using Serilog.Settings.AppSettings package so each service project will read its own configuration (Ex: separate Microsoft SQL Server) from <appSettings> section in service web.config useing the ReadFrom.AppSettings() extension method on your LoggerConfiguration
Sample Logger Class
public static class Logger
{
private static readonly ILogger _dbLogger;
static Logger()
{
_dbLogger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.CreateLogger();
}
public static void Log(string error)
{
_dbLogger.Error(error);
}
}
Sample appSettings configuration
<add key="serilog:using:MSSqlServer" value="Serilog.Sinks.MSSqlServer" />
<add key="serilog:write-to:MSSqlServer.connectionString" value="Server=..."/>
<add key="serilog:write-to:MSSqlServer.tableName" value="Logs"/>
<add key="serilog:write-to:MSSqlServer.autoCreateSqlTable" value="true"/>
There is a library from Serilog (MSSQL-Server)

How to reload appsettings.json at runtime each time it changes in .NET core 1.1 console application?

I attempted to reproduce the method described in this great article by Andrew Lock. However, I am unable to get this running in a .NET core 1.1 console application. When the appsettings.json file is changed and saved, the changes are not reflected in the application without restarting it.
There are multiple files involved, so I created the smallest example I could come up on github. I also provided details in the README.MD file on github.
Any help in resolving this would be most appreciated. Please keep in mind I am new to .NET core, and not an experienced developer. And this is my first question on stackoverflow... Thanks in advance!
The key thing to understand is scope.
There are three scopes in ASP.NET Core - transient, scoped, and singleton. IOptionsSnapshot is configured as a scoped service.
In ASP.NET Core, a scope is started for every request, so every request, you would get a new instance of IOptionsSnapshot, with updated configuration values.
In the example you provided, you are creating an IServiceProvider, and are fetching an instance of IMyService directly from the top level provider:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
var service = serviceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
Essentially, you're always using the same scope for every request to the service provider, so you're always getting the same instance of IOptionsSnapshot. Effectively, if you never create a new scope, all of your scoped services become singletons!
The way to fix this is to create a new scope each time you fetch the service:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
using (var scope = serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
}
This also becomes important if you're doing things like creating an EF Core DbContext outside the context of a request in ASP.NET Core app (or in a console app). Always create a new scope before accessing services from the service provider!
P.S. I've created a pull request to fix your sample :)

Programatically configure sso settings using kentor

I have an MVC application (.Net Framework 4.5) which is been there for the last three years and using Forms Authentication mechanism. Now we want to integrate SSO feature with the help of Okta. Using KentorIT Authentication services I was able to integrate Okta with my mvc application. In that, all the configurations are being set in the web.config file (eg: entityId, signOnUrl etc.). Is there a way to programmatically configure these sso settings? I found that KentorAuthServicesSection is the class that we have to instantiate to do the process. Currently its reading the settings from configuration file.
public class KentorAuthServicesSection : ConfigurationSection
{
private static readonly KentorAuthServicesSection current =
(KentorAuthServicesSection)ConfigurationManager.GetSection("kentor.authServices");
}
So modifying this ConfigurationManager.GetSection("kentor.authServices") part with a custom implementation will do the job? or is there any other good approach ?
You can just use the options classes directly -- no need to customize the GetSection.
I'm assuming you are using the Mvc module. In which case you want to set the options on the AuthServicesController during application startup, e.g.
Kentor.AuthServices.Mvc.AuthServicesController.Options = myOptions;
With your own construction of these same configuration classes. For example:
var spOptions = new SPOptions
{
EntityId = new EntityId("http://localhost:57294/AuthServices"),
ReturnUrl = new Uri("http://localhost..."),
//...
};
options = new KentorAuthServicesAuthenticationOptions(false)
{
SPOptions = spOptions
};
The false in this constructor tells it not to read from the configuration system.
There is a larger example in the OWIN sample project:
https://github.com/KentorIT/authservices/blob/v0.21.1/SampleOwinApplication/App_Start/Startup.Auth.cs#L54-L82

Web API Self hosting from a test assembly

I'm currently evaluating WebAPI and NancyFx for a new project about to start. I've managed to get Nancy to self host from a test assembly (by itself it uses asp.net hosting).
Is there any way to do the same with Web API? I would like to keep the web api project hosted on IIS, but i would like to spin it up from my test assembly, so i can run tests against it.
I have found some blogposts on how to use Autofac to scan controllers from another assembly (seems a little backwards only to get hosting from another assembly to work, but if it can be done, i guess that would be an option), but i would like to keep using Structuremap ioc for this project.
Managed to get it working with help from Mark Jones link. This is what i ended up with in my test assembly.
private static HttpSelfHostServer _server;
[BeforeTestRun]
public static void Setup()
{
var config = new HttpSelfHostConfiguration(Settings.TestUri);
WebApiConfig.Register(config); //map routes
IocConfig.Bootstrap(config); //configure dependency injection
_server = new HttpSelfHostServer(config);
_server.OpenAsync().Wait();
}
[AfterTestRun]
public static void TearDown()
{
_server.CloseAsync().Wait();
}

Architecture and Microsoft.AspNet.Providers

I have been Googling for hours and cant find an article that is exactly related to what I need.
I have a MVC4 site with the following layers:
Presentation layer (MVC4)
Business Layer
Data layer
I want to use the following provider:(installed using NuGet)
Install-Package Microsoft.AspNet.Providers
My question is more of an architectural one.
In my mind, I should install this (Microsoft.AspNet.Providers) in my data layer as it is code that talks to a membership database.
All the posts I can find, however, even by Hanselman just install it in the Presentation layer / MVC4.
I am very big on separation of concerns and am using dependency injection throughout my application.
Obviously I need the config for the provider in my web.config but want all the membership code in my data layer.
Any thoughts?
thanks
RuSs
PS. Would love to know the process of installing this in a data / repository layer using nuget. Slightly confused as to what DLLs Nuget is installing. If I install in my data layer, nuget doesnt update the MVC web.config.
The answer is quite simple actually: You should hide the providers behind an abstraction that you define in your business layer. This way you can write an adapter that implements this abstraction an wraps the provider and you can inject this adapter into your business layer using dependency injection. This way you will only have to reference the Microsoft.AspNet.Providers from your MVC4 project, and prevent any code from directly referencing the AspNet.Providers, which allows you to switch more easily later on.
Example:
// Define in business layer
public interface IAuthorizationService
{
bool bool IsCurrentUserInRole(string role);
}
public class SomeBusinessLayerCommand
{
private IAuthorizationService authorizer;
public SomeBusinessLayerCommand(
IAuthorizationService authorizer)
{
this.authorizer = authorizer;
}
public void SomeOperation()
{
if (this.authorizer.UserIsInRole("Admins"))
{
// some secret admin stuf
}
else
{
// some normal user stuf
}
}
}
And in your Presentation Layer you can define an adapter:
public class MembershipAdapter : IAuthorizationService
{
public bool IsCurrentUserInRole(string role)
{
return Roles.IsUserInRole(role);
}
}
And you can map IAuthorizationService to MembershipAdapter using your favorite DI container.

Resources