Creating and reading from appconfig.json - c#

I am trying to create config that will contains a list of servers, with extra values, something like
"Servers": [
{
"Name": ".",
"Type": "A"
},
{
"Name": "Fred",
"Type": "B"
}
]
Is that the correct way to structure the config file?
I then haven't been able to find a way to read from the config based on the above set up.
var test = Configuration.GetSection("Servers").GetChildren();
//List<Server> Servers = new List<Server>();
foreach (var testItem in test)
{
Server server = new Server()
{
//Name = testItem.GetValue(,"Name"),
//Type = testItem.GetValue("Type")
};
Servers.Add(server);
}
I'd appreciate some guidance on how to set up the config, and then how to read those values.
Thanks for reading

try this
List<Server> servers = configuration.GetSection("Servers").Get<List<Server>>();
public class Server
{
public string Name {get; set;}
public string Type {get; set;}
}

Related

Dynamically retrieve variable and argument values for NativeActivity

When I run the below code (C#) as a custom activity (compiled .dll is added to a nuget package and triggered in a UiPath sequence with some user defined variables/arguments. I am able to retrieve the name of the variable and it's type, but I cannot find the proper syntax to retrieve the value (I just want to convert it to a String, no need to do anything fancy). I can access some of the properties, so i know i am close. I have done my best to read the docs, but in this instance, it may be a little two abstract for me. I have gone through many interations and scoured as much of the internet as I can, but I cannot seem to figure it out.
using Newtonsoft.Json.Linq;
using System;
using System.Activities;
using System.Activities.Hosting;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
namespace AutoLog
{
public sealed class GetRootActivity : NativeActivity
{
public OutArgument<string> variables { get; set; }
protected override void Execute(NativeActivityContext context)
{
this.variables.Set((ActivityContext)context, Library.getLocalVariables(context));
}
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
metadata.AddDefaultExtensionProvider<GetRootActivity.WorkflowInstanceInfo>((Func<GetRootActivity.WorkflowInstanceInfo>)(() => new GetRootActivity.WorkflowInstanceInfo()));
}
public class Library
{
public static string getLocalVariables(NativeActivityContext context)
{
var properties = context.DataContext.GetProperties();
JArray variables = new JArray();
foreach(PropertyDescriptor p in properties)
{
JObject variable = new JObject();
variable["name"] = p.Name;
variable["type"] = p.PropertyType.ToString();
string string_value = "";
try
{
var myValue = context.DataContext.GetType().GetProperty(p.Name).GetValue(context.DataContext, null);
string_value = myValue.ToString();
}
catch(Exception e)
{
}
variable["value"] = string_value;
variables.Add(variable);
}
return variables.ToString();
}
}
}
}
Below is an example of the JSON it generates, as you can see, the "value" field is empty
[
{
"name": "a",
"type": "System.String",
"value": ""
},
{
"name": "b",
"type": "System.Boolean",
"value": ""
},
{
"name": "c",
"type": "System.Int32",
"value": ""
},
{
"name": "test",
"type": "System.String",
"value": ""
},
{
"name": "f",
"type": "System.String",
"value": ""
}
]
var myValue = context.DataContext.GetType().GetProperty(p.Name).GetValue(context.DataContext, null);
string_value = myValue.ToString();
can be changed to
string_value = p.GetValue(context.DataContext) as String;
I had previously tried this approach but got trying to make the cast dynamic, and apparently I had never tried the simpler solution.

Read configuration in to a collection of base class objects as child class objects

I have .Net core application, which is using the appsettigs.json file for holding configuration. I need to load a configuration section into a collection, without iterating through them. I know I can use Bind() method to bind the collection into a collection of same type. But here I am trying to get objects of the child class type in the collection, instead of base class type.
"Sections": [
{
"Name": "Section 1",
"Type":"type1"
},
{
"Name": "Section 2",
"Type":"type2"
},
{
"Name": "Section 3",
"Type":"type1"
},
{
"Name": "Section 4",
"Type":"type1"
},
{
"Name": "Section 5",
"Type":"type2"
}]
I am using the below code to read the config file.
var configBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
var Configuration = configBuilder.Build();
I know I can use Configuration.Bind()
The classes are
Public abstract class BaseSection:ISection
{
public string Name;
..
}
Public class Type1:BaseSection
{
public string Name;
..
}
Public class Type2:BaseSection
{
public string Name;
..
}
I need to read the configuration from the appsettings.json file to List such that the the for entry in config file with "type=type1" will have type in the collection Type1 obejct and "type=type2" will have type in the collection Type2 obejct.
So my collection from the above config entries should have
[
Object Of Type1
Object Of Type2
Object Of Type1
Object Of Type1
Object Of Type2
]
I don't want to read the data once and then type cast it.
Please share views and inputs. Thanks in advance.
You can use an intermediate list with binding, but you have to do some work to instanciate the right type. You can do something like that :
namespace CoreApp1
{
public class ConfigSectionItem: BaseSection
{
public string Type { get; set; }
}
class Program
{
static void Main(string[] args)
{
var configBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
var configuration = configBuilder.Build();
var confList = new List<ConfigSectionItem>();
configuration.GetSection("Sections").Bind(confList);
foreach (var confItem in confList)
{
var typeToBuild = Type.GetType($"CoreApp1.{confItem.Type}"); // Remember to do some checks with typeToBuild (not null, ...)
var newInstance = (BaseSection)Activator.CreateInstance(typeToBuild);
newInstance.Name = confItem.Name; // Use automapper or reflexion
// do what you want here with your newInstance
Console.WriteLine(newInstance.GetType().FullName + " " + newInstance.Name);
}
}
}
public abstract class BaseSection
{
public string Name;
}
public class Type1 : BaseSection
{
}
public class Type2 : BaseSection
{
}
}
Be sure to use Microsoft.Extensions.Configuration.Binder
And please be carefull to case sensitive in .json or do some work to capitalize:
"Type": "Type1"
"Type": "Type2"

How to create set of Multiple JSON with same header

I have a JSON that has the following pattern to be created before
hitting the API, See below
"recipientSetInfos":
[
{
"recipientSetMemberInfos":
[
{
"fax": "",
"email": ""
}
],
"recipientSetRole":
{
"SIGNER": "enum",
"APPROVER": "enum"
},
"signingOrder": 0
}
]
Using this predefined Format, i want to create Multiple signer set's,
like the below.
"recipientSetInfos":
[
{
"recipientSetMemberInfos":
[{
"email": "def#gmail.com"
}],
"recipientSetRole": "SIGNER"
}, {
"recipientSetMemberInfos": [{
"email": "abc#gmail.com"
}],
"recipientSetRole": "SIGNER"
}],
I am using C# Programming Language, if i just hard code it & send. It
works but if i want to create dynamically. How can i achieve this.
Currently I am using this like
RecipientSetInfo rec_Info = new RecipientSetInfo();
rec_Info.recipientSetMemberInfos = List_Emails;
rec_Info.recipientSetRole = "SIGNER";
List_Recipients.Add(rec_Info);
which gives an output of :
{
"recipientSetMemberInfos":
[
{"email":"abc#ae.com"},
{"email":"def#gmail.com"},
{"email":"fgh#gmail.com"}
],
"recipientSetRole":"SIGNER"
}
But using this logic, i am not getting the desired output. It is
considering all 3 emails as one.
Just to add, one more thing with the help of one user, i tried to code out this
foreach (var email in List_Emails)
{
var rec_Info = new RecipientSetInfo();
rec_Info.recipientSetRole = "SIGNER";
List_Recipients.Add(rec_Info);
}
But problem still exists, since "recipientSetInfos" has two subdivisions i.e. recipientSetRole & recipientSetMemberInfos within which "recipientSetMemberInfos" has one attribute Email.
So when i add the two lists together it comes out Email to be Null
"recipientSetInfos":
[
{"recipientSetMemberInfos":null,
"recipientSetRole":"SIGNER"
‌​},
{"recipientSetMemberInfos":null,
"recipientSetRole":"SIGNER"
}
]
Structure for both the elements i have created like -
public class RecipientSetMemberInfo
{
public string email { get; set; }
}
public class RecipientSetInfo
{
public List<RecipientSetMemberInfo> recipientSetMemberInfos { get; set; }
public string recipientSetRole { get; set; }
}
Please suggest ??
Your problem is that you create one RecipientSetInfo instead of one for each email.
The following will loop through List_Emails collection and will add them to the list List_Recipients.
foreach (var email in List_Emails)
{
var rec_Info = new RecipientSetInfo();
rec_Info.recipientSetRole = "SIGNER";
List_Recipients.Add(rec_Info);
}

How to serialize a C# object to json so it looks like "["starts-with", "$key", "user/john/"]"?

I'm trying to create a viewmodel in C# that can be serialized into a json document required by amazon S3. Documentation here. One of the properties looks like this,
["starts-with", "$key", "user/john/"]
What would the C# object look like so when it's serialized it would come out like this?
Rest of document looks like this.
{ "expiration": "2007-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "johnsmith" },
["starts-with", "$key", "user/john/"],
]
}
Just use a string array
string[] data = new string[] { "starts-with", "$key", "user/john/" };
The object structure for the second part would be something like
public class S3Expiration {
DateTime expiration { get; set; }
object[] conditions { get; set; }
}
and to populate it you would write something like
var expiration = new S3Expiration {
expiration = DateTime.Now,
conditions = new object[] {
new { acl = "public-read" },
new { bucket = "johnsmith" },
new string[] { "starts-with", "$key", "user/john/" }
}
};

Breaking out lists of objects in JSON via JSON.Net

I am building a server dashboard app. I want to take a list of disks from each server and create a list that displays the usage values for each.
Here's a JSON sample we're getting back...
{"server":"webster","disks":[ {"use": "91%", "used": "16G", "mount": "/", "free": "1.6G", "device": "/dev/mapper/vg_f12-lv_root", "total": "18G", "type": "ext4"} ,
{"use": "0%", "used": "0", "mount": "/dev/shm", "free": "500M", "device": "tmpfs", "total": "500M", "type": "tmpfs"} ,
{"use": "22%", "used": "40M", "mount": "/boot", "free": "145M", "device": "/dev/sda1", "total": "194M", "type": "ext4"} ,
{"use": "47%", "used": "52G", "mount": "/rsync", "free": "61G", "device": "/dev/sdb1", "total": "119G", "type": "ext3"} ]}
I get this far with the C# code:
WebClient c = new WebClient();
var data = c.DownloadString("http://192.0.0.40:8000/cgi-bin/df.py");
JObject o = JObject.Parse(data);
string serv = o["server"].Select(s => (string)s).ToString();
lblJson.Text = serv;
But I can't seem to extract "disks" into anything meaningful that I can plugin to a listview. I've tried pumping this into IList, but it always crashes or gives me some rude comments from Intellisense.
I do have a class built for this, but haven't figured out how to port the info into it. For reference, it's here:
public class drive
{
public string Usage;
public string usedSpace;
public string Mount;
public string freeSpace;
public string Device;
public string Total;
public string Type;
}
Note: The sources for JSON are Linux servers. Windows servers will supply data in a different format ultimately.
And then we have VMWare, but I'll flail on that later.
Thanks in advance.
var jsonObj = JsonConvert.DeserializeObject<RootObject>(json);
public class RootObject
{
[JsonProperty("server")]
public string Server;
[JsonProperty("disks")]
public List<Drive> Disks;
}
public class Drive
{
[JsonProperty("use")]
public string Usage;
[JsonProperty("used")]
public string usedSpace;
[JsonProperty("mount")]
public string Mount;
[JsonProperty("free")]
public string freeSpace;
[JsonProperty("device")]
public string Device;
[JsonProperty("total")]
public string Total;
[JsonProperty("type")]
public string Type;
}
There may be a better way to do this, but using the provided drive class, the following works to deserialize your provided JSON:
JObject o = JObject.Parse(data);
List<drive> drives = new List<drive>();
string server = (string)o["server"];
foreach (var d in o["disks"].Children())
{
drives.Add(new drive()
{
Usage = (string)d["use"],
usedSpace = (string)d["used"],
Mount = (string)d["mount"],
freeSpace = (string)d["free"],
Device = (string)d["device"],
Total = (string)d["total"],
Type = (string)d["type"]
});
}

Categories

Resources