Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Monday, May 13, 2019 3:01 PM
I am new to .Net core and thought I would start out by converting an existing .Net Framework console application over to be a .Net Core console application. The console application reads emails from an inbox and passes the email body contents to a class library which processes the body contents. The class library makes use of property.settings.default... to get values it needs to process the body contents. This was fairly straight forward using the Framework as I simply added the class' settings to the <applicationSettings> section of the console application's App.config file and the class' property settings were available for use by the class. With .Net Core, it doesn't appear to be as straight forward. I know through Google searches, the .Net Core method is to create an appSettings.json file and read settings from that. What I haven't been able to find is how to pass those settings to the class properly. What is the .Net Core way of doing this? Any examples are appreciated as I've been struggling with this for a while.
Thank you.
All replies (7)
Tuesday, May 14, 2019 11:35 AM âś…Answered | 1 vote
In my case of using IOptions with a .NET Core service, it was concerning getting the connectionstring being used by the EF Core DB.Model that is sitting in a Core classlib project (DAL) that was referenced by a Core WebAPI project.
So in order to pass the connectionstring from the WebAPI project to the DB.Model sitting in the classlib DAL project, I used a Connectionstring.cs to hold the connectionstring information that was retrieved from the asppsettings.json that was accessible by the WebAPI project and passed it to the DB.Model. The Connectionstring class was kept in a classlib project called Entities and the WebAPI project and the DAL classlib project had project refernce to Entities, and they know about the Connectionstring.cs.
Maybe, that's the part you are missing. I am just showing the flow of how the Connectionstring information got from one project to another project using IOptions with connectionstring info. that originated in the appsettings.json that was read by the startup of the Core WebAPI project.
Namespace Entities
{
public class ConnectionStrings
{
public string DefaultConnection { get; set; }
public string ProjectManagementConnection { get; set; }
}
}
using System.Net;
using DAL;
using Entities;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
namespace ProgMgmntCore2Api
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//DAL
services.AddTransient<IDaoProject, DaoProject>();
services.AddTransient<IDaoTask, DaoTask>();
services.AddTransient<IDaoCache, DaoCache>();
//Configuration
services.Configure<ConnectionStrings>(Configuration.GetSection("ConnectionStrings"));
The reset of what is in Startup.cs is irrelevant the main part is getting something out of an appsetings.json, which this would be happening at the Main() in the console program.
"ConnectionStrings": {
"DefaultConnection": "Dummy",
"ProjectManagementConnection":
"Server=DESKTOP-A86QNRQ\\SQLEXPRESS;Database=ProjectManagement;User Id=SA;Password=xxxxxxx"
},
"Serilog": {
"Using": ["Serilog.Sinks.Console"],
"MinimumLevel": "Error",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "c:\\logsapi\\log-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
"Properties": {
"Application": "My Application",
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
}
}
using System.Collections.Generic;
using System.Linq;
using DAL.Models.DB;
using Entities;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DAL
{
public class DaoCache : IDaoCache
{
private readonly IOptions<ConnectionStrings> _options;
public DaoCache(IOptions<ConnectionStrings> options)
{
_options = options;
}
public DtoCache GetCache()
{
var dtocache = new DtoCache
{
ProjectTypes = new List<DtoProjectType>(),
Statuses = new List<DtoStatus>(),
Resources = new List<DtoResource>(),
Durations = new List<DtoDuration>()
};
using (var context = new ProjectManagementContext(_options))
{
var projectypes = (from a in context.ProjectTypes select a).ToList();
CreateProjectTypes(dtocache, projectypes);
var statuses = (from a in context.Statuses select a).ToList();
CreateStatuses(dtocache, statuses);
var resources = (from a in context.Resources select a).ToList();
CreateResources(dtocache, resources);
var durations = (from a in context.Durations select a).ToList();
CreateDurations(dtocache, durations);
}
return dtocache;
}
}
using Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace DAL.Models.DB
{
public partial class ProjectManagementContext : DbContext
{
private readonly IOptions<ConnectionStrings> _options;
public ProjectManagementContext(IOptions<ConnectionStrings> options)
{
_options = options;
}
public ProjectManagementContext(DbContextOptions<ProjectManagementContext> options)
: base(options)
{
}
public virtual DbSet<Projects> Projects { get; set; }
public virtual DbSet<Tasks> Tasks { get; set; }
public virtual DbSet<ProjectTypes> ProjectTypes { get; set; }
public virtual DbSet<Durations> Durations { get; set; }
public virtual DbSet<Resources> Resources { get; set; }
public virtual DbSet<Statuses> Statuses { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(new AppConfiguration(_options).GetProjectMgmntConn());
}
}
}
using Entities;
using Microsoft.Extensions.Options;
namespace DAL
{
public class AppConfiguration
{
private readonly string _projectManagementConnection = "";
private readonly IOptions<ConnectionStrings> _options;
public AppConfiguration(IOptions<ConnectionStrings> options)
{
_options = options;
_projectManagementConnection = _options.Value.ProjectManagementConnection;
}
public string GetProjectMgmntConn() => $"{_projectManagementConnection}";
}
}
Monday, May 13, 2019 9:07 PM
One uses IOptions in ASP.NE Core solutions to read appsettings.json file into a class/object that can be used by another class/object that is done with Core's IoC services passing a class/object into another class/object by means of dependency injection via a class/object's constructor, which is called constrictor injection in using dependency injection used by .NET Core.
https://www.tutorialsteacher.com/ioc
https://www.codeproject.com/Tips/657668/Dependency-Injection-DI
https://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/
https://medium.com/@kritner/net-core-console-application-ioptions-t-configuration-ae74bfafe1c5;
Tuesday, May 14, 2019 7:27 AM
Hi rsine,
Thank you for posting here.
If you use ASP.NET Core, you can refer to the following links "how to getting value from appsettings.json".
If you use .NET Core, you can right click on your project, select Add> New Item to create a json or configuration file.
Best Regards,
Wendy
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].
Tuesday, May 14, 2019 7:55 AM
Hi rsine,
Thank you for posting here.
If you use ASP.NET Core, you can refer to the following links "how to getting value from appsettings.json".
If you use .NET Core, you can right click on your project, select Add> New Item to create a json or configuration file.
Best Regards,
Wendy
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].
How do you know that the poster is not using Core 3.0 that works with Windows desktop solutions? The poster is working with a Core console program that doesn't have controllers like an ASP.NET Core MVC solution has that the link you have provided is talking about. It's coming to the point and soon, that posts made about .NET Core may not apply solely to Web based solutions.
Tuesday, May 14, 2019 10:33 AM
DA924x,
I had looked at one of the links you'd provided (https://medium.com/@kritner/net-core-console-application-ioptions-t-configuration-ae74bfafe1c5) before posting to the forum. What I couldn't figure out from that link was how to implement the IOptions. I believe the link's ApiConfig and SomeClass classes are both in the same project. In my situation, I have a console application which references a class from a different project. Using the Framework, I simply took the settings for the referenced class and added to the App.config of the console application so the Properties.Settings.Default... values used by the class would work. With .Net Core, this isn't an option. So, I'm thinking I need to write the class my console application references to either have static properties which the console application can set prior to using the class or add to the referenced class an ApiConfig class and then have the class' constructor use the IOptions<ApiConfig>. I presume then (using the link's example) my console application would have this:
var serviceCollection = new ServiceCollection();
serviceCollection.AddOptions();
serviceCollection.Configure<MyReferencedClass.ApiConfig>(configuration.GetSection(nameof(ApiConfig)));
this.ServiceProvider = serviceCollection.BuildServiceProvider();
Is my presumption correct?
Thank you for your willingness to help. I do appreciate it as I've been struggling with this for a while.
Tuesday, May 14, 2019 4:25 PM
DA924x,
Thanks for the example and confirming that I was at least somewhere near the right track. I ended up adding a ConfigSettings class to my email processing class and in my email reader class, I added a reference to my EmailProcessor class. Here is what I have so far (note, this is just rough code I've been using to try to figure this all out):
EmailReader console application:
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Extensions.DependencyInjection;
using EmailProcessor;
namespace EmailReader
{
class Program
{
static IConfigurationRoot configuration;
static IServiceProvider serviceProvider;
static void Main(string[] args)
{
configuration = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetParent(AppContext.BaseDirectory).FullName)
.AddJsonFile("appSettings.json", true, true)
.Build();
EmailReaderSettings emailReaderSettings = configuration.GetSection("EmailReader").Get<EmailReaderSettings>();
//service collection are were we register our services
var serviceCollection = new ServiceCollection();
serviceCollection.AddOptions();
serviceCollection.AddTransient<EmailProcessor.Class1>();
serviceCollection.Configure<EmailProcessor.ConfigSettings>(configuration.GetSection("EmailProcessor"));
//service provider is where we get our services
serviceProvider = serviceCollection.BuildServiceProvider();
var emailProcessor = serviceProvider.GetService<EmailProcessor.Class1>();
emailProcessor.ProcessFile("test");
}
}
}
EmailProcessor ConfigSettings class:
using System;
using System.Collections.Generic;
using System.Text;
namespace EmailProcessor
{
public class ConfigSettings
{
public string SmtpHost { get; set; } = "";
}
}
EmailProcessor Class1 class
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace EmailProcessor
{
public class Class1
{
private readonly IOptions<ConfigSettings> _configSettings;
public Class1(IOptions<ConfigSettings> options)
{
this._configSettings = options;
}
public void ProcessFile(string file)
{
string smtpHost = _configSettings.Value.SmtpHost;
}
}
}
And of course my appSettings.json:
{
"EmailReader": {
"OutputDirectory": "c:\temp"
},
"EmailProcessor": {
"SmtpHost": "somesmtphost"
}
}
Again, this is all rough code which I can clean up. The main thing was to be able to get the settings for the EmailProcessor to the EmailProcessor.Class1 class and thanks to your help, I can do this. Thank you so much.
Tuesday, May 14, 2019 5:09 PM
**Again, this is all rough code which I can clean up. The main thing was to be able to get the settings for the EmailProcessor to the EmailProcessor.Class1 class and thanks to your help, I can do this. Thank you so much. **
I am glad it worked out for you.