How to dump entire appsettings.json file in ASP.NET Core Web API - asp.net-core-webapi

I am trying to create a simple GET API endpoint which will return the JSON of the current environment appsettings.json file, for example for the development environment it will return the contents of appsettings.Development.json file and for production environment it will return the contents of appsettings.Production.json file.
I don't know a nice way to dump the entire config file. What I know though is ways to read single config values through the injected config["Key"] or read a section through
config.GetSection("SectionName").Get<MyCustomSectionClass>()
approach. These options are not feasible as the file is big and the content may change.
This is an ASP.NET Core 6 Core Web API application, created through the default Visual Studio template.

If you want to return entire appsettings.xxx.json file, You can try this simple demo. I not sure if there is a better method, But this method works well in my project.
using Newtonsoft.Json;
private readonly IWebHostEnvironment _env;
public WeatherForecastController(IWebHostEnvironment env)
{
_env = env;
}
[HttpGet]
public IActionResult Get()
{
if (_env.IsDevelopment())
{
var path = Path.Combine(_env.ContentRootPath, "appsettings.Development.json");
string json = System.IO.File.ReadAllText(path);
object jsonObject = JsonConvert.DeserializeObject(json);
return Ok(jsonObject);
}else if (_env.IsProduction())
{
//read from appsettings.Production.json
return Ok();
}
else
{
//..........
return Ok();
}
}

Related

Copying raw html from a file into a razor page, in aspnet core?

I'm moving an existing ASP.NET/MVC app to aspnet core, and there's a bit where I'm not sure of the cleanest solution.
The issue is that we have a shared view that is called from a number of controllers. There's a chunk of html that is loaded from a file by the controller, and then is inserted into the page by the view using #Html.Raw().
The existing code in .NET Framework is using an extension method on Controller to get the contents of the file:
public static class ControllerExtension
{
public static string GetContents(this Controller controller, string path)
{
var filepath = controller.Server.MapPath(path);
var contents = System.IO.File.ReadAllText(filepath);
return contents;
}
}
This, of course, does not work in aspnet core. There is no Server.MapPath().
Googling around I found that the recommended approach is to use IWebHostEnvironment. I could do that - inject it into my controller, and pass it to my GetContents() extension, but that's starting to have a bit of a whiff about it.
So I'm wondering, is there some other mechanism for doing the basic task?
Assume I have a number of files in a directory under wwwroot, each containing plain html.
What would be the cleanest way to have a controller include the contents of one of these files in a .cshtml view?
I've used the WebRootPath property of the environment to get to wwwroot and use relative paths from there. Example:
public class MyController
{
private readonly IWebHostEnvironment environment;
public MyController(IWebHostEnvironment environment)
{
this.environment = environment ?? throw new ArgumentNullException(nameof(environment));
}
public IActionResult GetContents(string path)
{
var contentPath = Path.Combine(environment.WebRootPath, path);
var content = System.IO.File.ReadAllText(contentPath);
// Do something with content and return
}
}
You would of course want more checks to validate the user-provided path before attempting to read the file. Also, would likely make this async unless you cache the content and normally serve the memory-cached data.

Read appsettings.json keys in methods other than Main Program.cs .NetCore 3.1 console app

Basically I have to call a REST API from a .netcore console app which will return me some xml and then this console app will need to create a csv file from that xml.
I need to keep the REST API url and csv path in my appsettings.config.
I have created two keys for that.
Now I don't want to read these keys in my main method but I am building ConfigurationBuilder in my main method and therefore its available only in Main method.
Code in my Main method looks like below.
configuration = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true)
.AddEnvironmentVariables()
.Build();
where configuration is static IConfiguartion configuration = null at Program.cs class level.
For now I have made this ConfigurationBuilder as a class level static variable , initilaizing it in Main then reading it elsewhere but not sure if its a good approach or there's some better way of doing this?
Any suggestions would be appreciated.
In my opinion you should use Dependency Injection like described in #Marco Luzzaras comment.
But if it is not possible in you scenario you can also access the same configuration by encapsule everything in a Singleton
public class ConfigurationProvider
{
private static IConfiguration _instance;
public static IConfiguration Instance
{
get
{
if(_instance == null)
{
_instance = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", optional: true)
.AddEnvironmentVariables()
.Build();
}
return _instance;
}
}
}
... and use it everywhere you need it.
dotnet fiddle Example

ITelemetryProcessor behavior when deployed to AppService

I have created a custom telemetry processor which is adding customer properties to the telemetry items. When running locally, I don’t see any issue and I am seeing the properties being added(both in release and debug mode) and logged to the AppInsights.
When deployed to app service, I am seeing the logs, but the properties being added by the telemetry processor are missing.
I am using .Net Core 2.1 and the Application insights NuGet version is 2.3.0. Is there a way to debug why this is happening? Also is anyone aware if this is a known issue?
Can you share your code which adds application insights and the telemetry processor? It should be something like this:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<MyFirstCustomTelemetryProcessor>();
// If you have more processors:
services.AddApplicationInsightsTelemetryProcessor<MySecondCustomTelemetryProcessor>();
// ...
}
Can you try to print the list of TelemetryProcessors registered with the TelemetryConfiguration instance? You can constructor inject TelemetryConfiguration to a controller class, and print out the list. Something like shown below.
string tpList;
public ValuesController(TelemetryConfiguration tc)
{
var tps = tc.TelemetryProcessors;
foreach(var tp in tps)
{
var s = tp.GetType().ToString();
tpList += s;
}
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", tpList };
}
This should confirm if the TelemetryProcessor is even in the config.
Also, when you say works local - do you mean when running from Visual Studio? VS alters behavior, so can try to run locally outside of VS, and see if it reproes.

ASP.NET MVC Bundle each file seperate in debug mode

How render each bundled file separate in debug mode?
I want to have rendered css and js file separate in my view, because it is hard to debug javascript files when all files are bundled.
You need to create simple BundleHelper class.
After that in your *.cshtml file yo can use
#BundleHelper.RenderScripts("~/bundles/js")
#BundleHelper.RenderStyles("~/bundles/style")
public class BundleHelper
{
private static IEnumerable<string> GetOriginalFilePaths(string bundlePath)
{
var resolver = new BundleResolver(BundleTable.Bundles);
IEnumerable<string> scriptPaths = resolver.GetBundleContents(bundlePath).ToList();
return scriptPaths;
}
public static IHtmlString RenderScripts(string bundlePath )
{
if (BundleTable.EnableOptimizations) return Scripts.Render(bundlePath);
var scriptPaths = GetOriginalFilePaths(bundlePath);
return Scripts.Render(scriptPaths.ToArray());
}
public static IHtmlString RenderStyles(string bundlePath)
{
if (BundleTable.EnableOptimizations) return Styles.Render(bundlePath);
var stylePaths = GetOriginalFilePaths(bundlePath);
return Styles.Render(stylePaths.ToArray());
}
}
In production it will work as you want and in development will work like as you haven't used bundling.

Windows Store Application Place SQLite File in LocalState Folder

I am building a Windows 8 application using sql-net and mvvmcross for data access to a sqlite database. This would be applicable to any Win-8 or Win-Phone app.
I need to install an existing sqlite file on app start.
When using the connection you use syntax such as this
public FlashCardManager(ISQLiteConnectionFactory factory, IMvxMessenger messenger)
{
_messenger = messenger;
_connection = factory.Create("Dictionary.sqlite");
_connection.CreateTable<FlashCardSet>();
_connection.CreateTable<FlashCard>();
}
public void CreateCard(FlashCard flashCard)
{
_connection.Insert(flashCard);
}
That connection creates a file in: C:\Users\USER\AppData\Local\Packages\793fd702-171e-474f-ab3b-d9067c58709b_ka9b83fa3fse2\LocalState
My application uses an existing sqlite database file that I have created. I need to place it in this folder when the application is installed. How would I go about doing this?
Thanks,
JH
Make sure you have the database file you want your app to start off with in one of your apps folders (as in the folders visible in visual studios solution explorer). For this example I'll call this folder "Assets"
All you need to do then is copy this file to the LocalState folder the first time your app runs. This can be done in App.xaml.cs
private async void InitializeAppEnvironment()
{
try
{
if (!(await AppHelper.ExistsInStorageFolder(AppHelper.localFolder, dbName)))
{
StorageFile defaultDb = await AppHelper.installedLocation.GetFileAsync("Assets\\" + dbName);
await defaultDb.CopyAsync(AppHelper.localFolder);
}
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e);
}
}
I made an AppHelper class to simplify accessing the app data folders, here's the parts I used above:
static class AppHelper
{
public static StorageFolder installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
public static StorageFolder localFolder = ApplicationData.Current.LocalFolder;
public static async Task<bool> ExistsInStorageFolder(this StorageFolder folder, string fileName)
{
try
{
await folder.GetFileAsync(fileName);
return true;
}
catch (FileNotFoundException)
{
return false;
}
}
}
For a more detailed response on MVVM cross I found the current discussion about cross platform file placement in this discussion: Link
The current thought is that you have to inject platform specific code for this sort of functionality.

Resources