Reputation: 267
I am starting a new web application. The backend is in c# .net core and the front-end is a react app that is placed in the wwwroot with webpack. The admins of the web application can change some colors (button color, header color, etc.) These colors are saved in a database and should be injected in a style sheet. The production style sheet looks something like
.my-button {
background: ##main-color##
}
when the css is served i would like to replace ##main-color## with the color that is saved in the database.
In the startup i tried adding a middleware on the request pipeline. However the request to the css file is never triggered here.
In the previous application i used the exact same setup except .net framework was used instead of .net core. I used rewrite rules and a middleware on the request pipeline. The middleware then checked if the css file was requested. When this was the case i read the css file in memory and did a string replace before writing to the response.
I'm struggling to get this to work in .net core and i am wondering how i should implement something like the above?
Upvotes: 2
Views: 342
Reputation: 267
I ended up writing a custom IFileProvider
that returns a custom IFileInfo
and when the css was served the file will be read and altered in the CreateStream()
method.
This resulted in something like this:
public Stream CreateReadStream()
{
if (_text == null)
{
using (var scope = _container.BeginLifetimeScope())
{
var tenantBrandingService = scope.Resolve<ITenantBrandingService>();
var settings = tenantBrandingService.Get();
using (var stream = _realFile.CreateReadStream())
{
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
_text = Encoding.UTF8.GetString(memoryStream.ToArray())
.Replace("##mainColor##", settings.MainColor)
.Replace("##mainColorText##", settings.MainColorText);
}
}
}
}
return new MemoryStream(Encoding.UTF8.GetBytes(_text));
}
I used the custom IFileProvider
in the app.UseStaticFiles
and in the app.UseSpa
Upvotes: 0
Reputation: 683
I wouldn't change it at runtime. I would setup an automated deployment process which updates your css file before deployment. You could use this plungin in Azure Devops (or TFS) :https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens
But other CI-CD systems are able to do those kinds of tasks as well, maybe with some manual scripting..
But If you still want to update your css file during startup. I would update the program.cs
public class Program
{
public static void Main(string[] args)
{
var myColors = new Dictionary<string,string>();
try{
var connectionString = Environment.GetEnvironmentVariable("CssDBConnection");
//select values from DB into the dictionary
myColors = GrabCssColorsFromDatabase(connectionString);
}catch(Exception e){
//use default css values in the dictionary
}
finally{
InjectCss(myColors);
BuildWebHost(args).Run();
}
}
It's similar to this workaround for Nlogs non Layout Targets: https://github.com/NLog/NLog/wiki/WebService-target---Workaround-for-url-variables
If you want to update it on the fly (no new Deployment). Provide an IActionResultEndpoint which returns the injected CssFile.
The Endpoint could be /Home/Styles And again:
Upvotes: 3