Ich habe eine appsettings.json-Datei, die folgendermaßen aussieht:
{
"someSetting": {
"subSettings": [
"one",
"two",
"three"
]
}
}
Wenn ich mein Konfigurationsstammverzeichnis erstelle und so etwas mache, config["someSetting:subSettings"]
wird null zurückgegeben, und die tatsächlich verfügbaren Einstellungen lauten wie folgt:
config["someSettings:subSettings:0"]
Gibt es eine bessere Möglichkeit, den Inhalt someSettings:subSettings
einer Liste abzurufen ?
c#
asp.net-core
.net-core
Devlife
quelle
quelle
Could not load file or assembly 'Microsoft.Extensions.Configuration.Binder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified
Antworten:
Sie können den Konfigurationsordner verwenden, um eine starke Typdarstellung der Konfigurationsquellen zu erhalten.
Dies ist ein Beispiel aus einem Test, den ich zuvor geschrieben habe. Ich hoffe, es hilft:
[Fact] public void BindList() { var input = new Dictionary<string, string> { {"StringList:0", "val0"}, {"StringList:1", "val1"}, {"StringList:2", "val2"}, {"StringList:x", "valx"} }; var configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddInMemoryCollection(input); var config = configurationBuilder.Build(); var list = new List<string>(); config.GetSection("StringList").Bind(list); Assert.Equal(4, list.Count); Assert.Equal("val0", list[0]); Assert.Equal("val1", list[1]); Assert.Equal("val2", list[2]); Assert.Equal("valx", list[3]); }
Der wichtige Teil ist der Aufruf an
Bind
.Der Test und weitere Beispiele finden Sie auf GitHub
quelle
services.Configure<TOptions>
? Ich möchte Optionen aus den Konfigurationsfeldern einfügen, die ein Array enthaltenAngenommen, Sie sehen so
appsettings.json
aus:{ "foo": { "bar": [ "1", "2", "3" ] } }
Sie können die Listenelemente wie folgt extrahieren:
Configuration.GetSection("foo:bar").Get<List<string>>()
quelle
In .NetCore habe ich Folgendes getan:
Normales Setup:
Erstellen Sie in Ihrer appsettings.json einen Konfigurationsabschnitt für Ihre benutzerdefinierten Definitionen:
"IDP": [ { "Server": "asdfsd", "Authority": "asdfasd", "Audience": "asdfadf" }, { "Server": "aaaaaa", "Authority": "aaaaaa", "Audience": "aaaa" } ]
Erstellen Sie eine Klasse, um die Objekte zu modellieren:
public class IDP { public String Server { get; set; } public String Authority { get; set; } public String Audience { get; set; } }
in Ihrem Startup -> ConfigureServices
services.Configure<List<IDP>>(Configuration.GetSection("IDP"));
Dann in Ihrem Controller so etwas:
Public class AccountController: Controller { private readonly IOptions<List<IDP>> _IDPs; public AccountController(IOptions<List<Defined>> IDPs) { _IDPs = IDPs; } ... }
Nur als Beispiel habe ich es an anderer Stelle im obigen Controller wie folgt verwendet:
_IDPs.Value.ForEach(x => { // do something with x });
Edge Case
Für den Fall, dass Sie mehrere Konfigurationen benötigen, diese sich jedoch nicht in einem Array befinden können und Sie keine Ahnung haben, wie viele Untereinstellungen Sie gleichzeitig haben werden. Verwenden Sie die folgende Methode.
appsettings.json
"IDP": { "0": { "Description": "idp01_test", "IDPServer": "https://intapi.somedomain.com/testing/idp01/v1.0", "IDPClient": "someapi", "Format": "IDP" }, "1": { "Description": "idpb2c_test", "IDPServer": "https://intapi.somedomain.com/testing/idpb2c", "IDPClient": "api1", "Format": "IDP" }, "2": { "Description": "MyApp", "Instance": "https://sts.windows.net/", "ClientId": "https://somedomain.com/12345678-5191-1111-bcdf-782d958de2b3", "Domain": "somedomain.com", "TenantId": "87654321-a10f-499f-9b5f-6de6ef439787", "Format": "AzureAD" } }
Modell
public class IDP { public String Description { get; set; } public String IDPServer { get; set; } public String IDPClient { get; set; } public String Format { get; set; } public String Instance { get; set; } public String ClientId { get; set; } public String Domain { get; set; } public String TenantId { get; set; } }
Erstellen Sie eine Erweiterung für das Expando-Objekt
public static class ExpandObjectExtension { public static TObject ToObject<TObject>(this IDictionary<string, object> someSource, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public) where TObject : class, new() { Contract.Requires(someSource != null); TObject targetObject = new TObject(); Type targetObjectType = typeof(TObject); // Go through all bound target object type properties... foreach (PropertyInfo property in targetObjectType.GetProperties(bindingFlags)) { // ...and check that both the target type property name and its type matches // its counterpart in the ExpandoObject if (someSource.ContainsKey(property.Name) && property.PropertyType == someSource[property.Name].GetType()) { property.SetValue(targetObject, someSource[property.Name]); } } return targetObject; } }
ConfigureServices
var subSettings = Configuration.GetSection("IDP").Get<List<ExpandoObject>>(); var idx = 0; foreach (var pair in subSettings) { IDP scheme = ((ExpandoObject)pair).ToObject<IDP>(); if (scheme.Format == "AzureAD") { // this is why I couldn't use an array, AddProtecedWebApi requires a path to a config section var section = $"IDP:{idx.ToString()}"; services.AddProtectedWebApi(Configuration, section, scheme.Description); // ... do more stuff } idx++; }
quelle
public class Definitions : List<Defined> {}
. `{" Definitionen ": [{" Name ":" Somename "," Title ":" Sometitle "," Image ":" Some Image URL "}, {" Name ":" Somename "," Title ":" Sometitle " "," Image ":" some image url "}]}`var settingsSection = config.GetSection["someSettings:subSettings"]; var subSettings = new List<string>; foreach (var section in settingsSection.GetChildren()) { subSettings.Add(section.Value); }
Dies sollte Ihnen die Werte geben, die Sie benötigen, gespeichert in
subSettings
Entschuldigung für das Aufrufen eines halb alten Threads. Ich hatte Schwierigkeiten, eine Antwort zu finden, da viele Methoden wie
Get
und veraltet sindGetValue
. Dies sollte in Ordnung sein, wenn Sie nur eine einfache Lösung ohne den Konfigurationsordner benötigen. :) :)quelle
In meinem Fall Konfiguration
services.Configure<List<ApiKey>>(Configuration.GetSection("ApiKeysList"));
wurde nicht geladen, da die Eigenschaften schreibgeschützt waren und es keinen Standardkonstruktor gab
**//not working** public class ApiKey : IApiKey { public ApiKey(string key, string owner) { Key = key; OwnerName = owner; } public string Key { get; } public string OwnerName { get;} }
//Arbeiten
public class ApiKey : IApiKey { public ApiKey(){}//Added default constructor public ApiKey(string key, string owner) { Key = key; OwnerName = owner; } public string Key { get; set; } //Added set property public string OwnerName { get; set; } //Added set property }
quelle