I am using Visual Studio 2017, Version 15.7.2 and working with an answer in the following link:
net core 1 (dnx 4.5.1) with enterpriselibrary 6 - setting up the connection string
public class DataConfiguration
{
public string DefaultDatabase { get; set; }
public List<ConnectionStringSettings> ConnectionStrings { get; set; }
}
public class Startup
{
public Startup(IConfiguration configuration)
{
//Get the Database Connections from appsettings.json
DataConfig = configuration.Get<DataConfiguration>();
var defaultDb = DataConfig.ConnectionStrings?.Find(c => c.Name == DataConfig.DefaultDatabase);
DatabaseFactory.SetDatabases(() => new SqlDatabase(defaultDb.ConnectionString), GetDatabase);
Configuration = configuration;
}
public Database GetDatabase(string name)
{
var dbInfo = DataConfig.ConnectionStrings.Find(c => c.Name == name);
if (dbInfo.ProviderName == "System.Data.SqlClient")
{
return new SqlDatabase(dbInfo.ConnectionString);
}
return new MySqlDatabase(dbInfo.ConnectionString);
}
The part I cannot get to work is:
//Get the Database Connections from appsettings.json
DataConfig = configuration.Get<DataConfiguration>();
configuration.Get<DataConfiguration>() returns an empty instance of DataConfiguration. I expected it to populate or bind to DataConfiguration in the appsettings file.
My appsettings.json:
{
"DataConfiguration": {
"DefaultDatabase": "MyDB",
"ConnectionString": "Server=MyServer;Database=MyDB;Integrated Security=True;MultipleActiveResultSets=true",
"ProviderName": "System.Data.SqlClient"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
My Startup.cs
public class DataConfiguration
{
public string DefaultDatabase { get; set; }
public string ConnectionString { get; set; }
public string ProviderName { get; set; }
}
public class Startup
{
public DataConfiguration DataConfig;
public Startup(IConfiguration configuration)
{
DataConfig = configuration.Get<DataConfiguration>();
DatabaseFactory.SetDatabases(() => new SqlDatabase(DataConfig.ConnectionString), GetDatabase);
Configuration = configuration;
}
public Database GetDatabase(string name)
{
if(DataConfig.ProviderName == "System.Data.SqlClient")
{
return new SqlDatabase(DataConfig.ConnectionString);
}
return null;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var config = new DataConfiguration();
Configuration.Bind("DataConfiguration", config);
services.AddMvc();
services.AddSingleton(config);
//services.AddSingleton<IConfiguration>(Configuration);
services.AddTransient<IPatientRepository, PatientRepository>();
}
What am I missing?
So, if you want use settings file this way, you have to write:
var DataConfig = new DataConfiguration();
Configuration.GetSection(nameof(DataConfiguration)).Bind(DataConfig);
But usually settings and configurations uses another way:
https://learn.microsoft.com/aspnet/core/fundamentals/startup?view=aspnetcore-2.0
or even easier:
services.Configure<DataConfiguration>configuration.GetSection(nameof(DataConfiguration)))
services.AddScoped(serviceProvider =>
{
var options = serviceProvider.GetRequiredService<IOptions<DataConfiguration>>();
return new SqlDatabase(options.Value.ConnectionString);
});
I hope its clear, but maybe final example should be slightly corrected :)
Related
According to automapper docs, I can map nested objects to destination using IncludeMembers function. I have issues with next sample.
Code is available on net fiddle, below is quick reference:
How I map:
var source = new CategoryStatus
{
Subgroup = new CategorySubgroup
{
SubgroupCode = "SubgroupCode",
CategoryGroup = new CategoryGroup { GroupCode = "SubgroupCode" }
}
};
var result = Mapper.Map<Dest, CategoryStatus>(source);
My classes:
public class Dest
{
public string SubgroupCode { get; set; }
public string GroupCode { get; set; }
}
public class CategoryStatus
{
public CategorySubgroup Subgroup { get; set; }
}
public class CategorySubgroup
{
public string SubgroupCode { get; set; }
public CategoryGroup CategoryGroup { get; set; }
}
public class CategoryGroup
{
public string GroupCode { get; set; }
}
My Configuration:
var cfg2 = new MapperConfiguration(cfg => {
cfg.CreateMap<CategoryStatus, Dest>()
.IncludeMembers(x => x.Subgroup);
cfg.CreateMap<CategoryGroup, Dest>();
cfg.CreateMap<CategorySubgroup, Dest>()
.IncludeMembers(x => x.CategoryGroup);
});
Error:
[System.ArgumentException: Property 'System.String GroupCode' is not defined for type 'CategorySubgroup']
Any ideas about configuration setup? Automapper version is 10.0.0
Update
Version 9.0.0 works. Possible latest will also work, but it contains some breaking changes for me, so I didn't test it.
I'm trying to determine if it's possible to configure the column options for serilog sink mssqlserver in the appsettings.json file for an ASP.Net Core 2 project.
I create and configure the logger in the Program.cs file.
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
//.Enrich.WithProperty("AppName", "One Badass App") // Adds property to XML structure in properties column
.ReadFrom.Configuration(Configuration)
.CreateLogger();
try
{
Log.Information("Starting web host");
BuildWebHost(args).Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
I can build the configuration file from the appsettings.json file, which contains a Serilog node with information for which connection string and table to use.
{
"AppSettings": {
"Application": {
"Name": "Payment Processing API",
"Version": "1.0"
}
},
"ConnectionStrings": {
"localPaymentProcessingDb": "Server=(localdb)\\mssqllocaldb;Database=PaymentProcessing;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Server=(localdb)\\mssqllocaldb;Database=PaymentProcessing;Trusted_Connection=True;MultipleActiveResultSets=true",
"tableName": "Logs"
}
}
]
}
There's an open issue on Github for this, but I haven't found any other information about it.
If column options can't be configured in the appsettings.json, where and how should they be configured in an ASP.Net Core 2 project?
If anyone else stumbles across this same issue the linked GitHub issue in the question now contains the answer:
This is now possible with the latest SQL sink and
Serilog.Settings.Configuration packages.
Also, I know this question asks for a .NET Core 2 answer, and it sounds like the linked GitHub page answers this for 2, I am using .NET Core 3.1 and the following worked for me (hopefully it works for 2 as well)
I installed the Serilog.Settings.Configuration Nuget package and used the following Serilog appsettings.json configuration:
"Serilog":{
"MinimumLevel":"Information",
"WriteTo":[
{
"Name":"MSSqlServer",
"Args":{
"connectionString":"DbContext",
"tableName":"EventLog",
"autoCreateSqlTable":true,
"columnOptionsSection":{
"addStandardColumns":[
"LogEvent"
],
"removeStandardColumns":[
"MessageTemplate",
"Properties"
]
}
}
}
]
}
For accessing Serilog from appsettings in Code, you could bind Serilog node to Serilog class.
Here are the detail steps.
1. Create Serilog Configuration Class
public class SerilogConfiguration
{
public LogEventLevel MinimumLevel { get; set; }
public List<WriteTo> WriteTo { get; set; }
}
public class WriteTo
{
public string Name { get; set; }
public Args Args { get; set; }
}
public class Args
{
public string ConnectionString { get; set; }
public string TableName { get; set; }
public List<StandardColumn> Add { get; set; }
public List<StandardColumn> Remove { get; set; }
}
Configure appsettings.json
Code:
{
"Serilog": {
"MinimumLevel": "Error",
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "<our connection string>",
"tableName": "Log",
"Remove": [ "Properties" ],
"Add": [ "LogEvent" ]
}
}
]
}
}
Bind appsetting.json to class
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SerilogConfiguration>(Configuration.GetSection("Serilog"));
}
Access Configuration
public class HomeController : Controller {
private readonly SerilogConfiguration _configuration;
public HomeController(IOptions<SerilogConfiguration> configuration)
{
_configuration = configuration.Value;
}
public IActionResult AppSettings()
{
var columnOptions = new ColumnOptions();
var MSSqlServer = _configuration.WriteTo.Where(wt => wt.Name == "MSSqlServer").FirstOrDefault();
// Don't include the Properties XML column.
foreach(var columnRemove in MSSqlServer.Args.Remove)
{
columnOptions.Store.Remove(columnRemove);
}
// Do include the log event data as JSON.
foreach (var columnAdd in MSSqlServer.Args.Add)
{
columnOptions.Store.Add(columnAdd);
}
Log.Logger = new LoggerConfiguration()
.WriteTo.MSSqlServer(MSSqlServer.Args.ConnectionString, MSSqlServer.Args.TableName, columnOptions: columnOptions,
restrictedToMinimumLevel: _configuration.MinimumLevel)
.CreateLogger();
return Ok("OK");
} }
I am getting very confused with the Funq container.
I have the following:
public interface IConnectionString
{
string ConnectionString { get; set; }
}
public class FoundationConnection : IConnectionString
{
public FoundationConnection(string connectionString)
{
ConnectionString = connectionString;
}
public string ConnectionString { get; set; }
}
Now in my AppHost, I would like to register
container.Register<IConnectionString>(c=> new FoundationConnection(AppSettings.Get(
"FoundationConnectionString", "").MapHostAbsolutePath()));
In my ServiceInterface I want to call this injected method somehow:
public class ServiceInterface : Service
{
public IConnectionString foundationConnection { get; set; }
public object Any(SomeRequest request)
{
string injectedProperty = foundationConnection.ConnectionString;
}
}
}
Issue is that foundationConnection is null and never injected.
I hope this makes sense?
Personally I would use AppSettings to access config settings which would allow you to source configuration from a number of different and cascading configuration sources.
But I've tested this using these types:
public interface IConnectionString
{
string ConnectionString { get; }
}
class FoundationConnectionString : IConnectionString
{
public FoundationConnectionString(string connectionString)
{
ConnectionString = connectionString;
}
public string ConnectionString { get; set; }
}
and it's working correctly after registering it in the AppHost.Configure():
public override void Configure(Container container)
{
container.Register<IConnectionString>(c =>
new FoundationConnectionString("My Connection"));
}
and accessing it from a test service:
[Route("/test")]
public class Test : IReturn<string> { }
public class TestService : Service
{
public IConnectionString Config { get; set; }
public object Any(Test request)
{
return Config.ConnectionString;
}
}
Which returns "My Connection" when called.
I can't seem to be able to get the proper instance injected into a class ctor. Here is what I am trying to do:
class Program
{
static void Main(string[] args)
{
WindsorContainer container = new WindsorContainer();
container.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(() => GetSessionFactory("1"))
.Named("1"),
Component.For<ISessionFactory>()
.UsingFactoryMethod(() => GetSessionFactory("2"))
.Named("2"));
container.Register(
Component.For<IRepository>()
.ImplementedBy<Repository>()
.DependsOn(container.Resolve<ISessionFactory>("1")),
Component.For<IReadOnlyRepository>()
.ImplementedBy<ReadOnlyRepository>()
.DependsOn(container.Resolve<ISessionFactory>("2")));
var connectionString1 = container.Resolve<IRepository>().Factory.ConnectionString;
var connectionString2 = container.Resolve<IReadOnlyRepository>().Factory.ConnectionString;
//These should not be equal!!!
Console.WriteLine(connectionString1);
Console.WriteLine(connectionString2);
}
public static SessionFactory GetSessionFactory(string connectionString)
{
return new SessionFactory { ConnectionString = connectionString };
}
public static bool Blah(Type accepted)
{
int d = 3;
return true;
}
}
public interface ISessionFactory
{
string ConnectionString { get; set; }
}
public class SessionFactory : ISessionFactory
{
public string ConnectionString { get; set; }
}
public interface IRepository
{
ISessionFactory Factory { get; set; }
}
public class Repository : IRepository
{
public ISessionFactory Factory { get; set; }
public Repository(ISessionFactory factory)
{
this.Factory = factory;
}
}
public interface IReadOnlyRepository
{
ISessionFactory Factory { get; set; }
}
public class ReadOnlyRepository : IReadOnlyRepository
{
public ISessionFactory Factory { get; set; }
public ReadOnlyRepository(ISessionFactory factory)
{
this.Factory = factory;
}
}
Can anyone spot the problem?
try this:
container.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(() => GetSessionFactory("1"))
.Named("1"),
Component.For<ISessionFactory>()
.UsingFactoryMethod(() => GetSessionFactory("2"))
.Named("2"),
Component.For<IRepository>()
.ImplementedBy<Repository>()
.DependsOn(Dependency.OnComponent(typeof(ISessionFactory),"1")),
Component.For<IReadOnlyRepository>()
.ImplementedBy<ReadOnlyRepository>()
.DependsOn(Dependency.OnComponent(typeof(ISessionFactory), "2")));
i am new in orchard module development.i create a module.when i try to save data.
i use this code fore save data
public ActionResult Create(FormCollection input)
{
var product = contentManager.New<ProductPart>("Product");
product.EmployeeName = input["EmployeeName"];
product.EmployeeFathersName = input["EmployeeFathersName"];
product.DOB = Convert.ToDateTime(input["DOB"]);
product.Email = input["Email"];
product.Address = input["Address"];
product.JoiningDate = Convert.ToDateTime(input["JoiningDate"]);
if (!ModelState.IsValid)
{
return View(product);
}
contentManager.Create(product);
return RedirectToAction("Index");
}
this class i use in Model
public class ProductRecord:ContentPartRecord
{
public virtual string EmployeeName { get; set; }
public virtual string EmployeeFathersName { get; set; }
public virtual DateTime DOB { get; set; }
public virtual string Email { get; set; }
public virtual string Address { get; set; }
public virtual DateTime JoiningDate { get; set; }
}
public class ProductPart : ContentPart<ProductRecord>
{
/*
public int Id
{
get { return Record.Id; }
set{Record.Id = value;}
}
*/
[Required]
public string EmployeeName
{
get { return Record.EmployeeName; }
set { Record.EmployeeName = value; }
}
[Required]
public string EmployeeFathersName
{
get { return Record.EmployeeFathersName; }
set { Record.EmployeeFathersName = value; }
}
[Required]
public DateTime DOB
{
get { return Record.DOB; }
set { Record.DOB = value; }
}
[Required]
public string Email
{
get { return Record.Email; }
set { Record.Email = value; }
}
[Required]
public string Address
{
get { return Record.Address; }
set { Record.Address = value; }
}
[Required]
public DateTime JoiningDate
{
get { return Record.JoiningDate;}
set { Record.JoiningDate = value; }
}
}
i use content type "Product" but when it goes orchard ContentCreateExtension in belows method
public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
var contentItem = manager.New(contentType);
if (contentItem == null)
return null;
var part = contentItem.Get<T>();
if (part == null)
throw new InvalidCastException();
return part;
}
here i face var part is null that means it content part is null.
please help me....
Have you setup your migrations class?
i.e.
public class Migrations : DataMigrationImpl {
public int Create() {
SchemaBuilder.CreateTable("ProductRecord",
table => table
.ContentPartRecord()
.COLUMNS NEED TO BE SPECIFIED
);
ContentDefinitionManager.AlterTypeDefinition("Forum",
cfg => cfg
.WithPart("ProductPart")
.WithPart("CommonPart")
);
Also have you setup your repository?
i.e.
public class ProductPartHandler : ContentHandler {
public ProductPartHandler(IRepository<ProductPartRecord> repository) {
Filters.Add(StorageFilter.For(repository));
}
In addition to the Nicholas answer, I want to mention, that missing driver for the ProductPart can cause such error. Make sure, that you have at least empty driver defined.
public class ProductPartDriver : ContentPartDriver<ProductPart> {}
Just went through a similar situation, be sure that the handler class is declared as public.