Find path/namespace of JToken in a Newtonsoft JObject - c#

I have the following code example (C# using Newtonsoft Json.NET) that serializes a Json string into a JObject:
var obj = JObject.Parse("{\"F01\" : \"f01\", " +
"\"F02\" : \"f02\", " +
"\"L01\" : [" +
"{" +
"\"L01F01\" : \"l01f01\", " +
"\"L01F02\" : \"l01f02\"" +
"}, " +
"{" +
"\"L01F01\" : \"l01f01\", " +
"\"L01F02\" : \"l01f02\"" +
"}, " +
"{" +
"\"L01F03\" : \"l01f03\" " +
"}, " +
"{" +
"\"L01F03\" : \"l01f03\", " +
"\"L01L02\" : [" +
"{" +
"\"L01L02F01\" : \"l01l02f01\"" +
"}" +
"]" +
"}" +
"]" +
"}");
Notice that the JSON has a dynamic structure where not all items in arrays has same names and attributes.
And I make the following JTokens:
var test01 = obj["F01"];
var test02 = obj["L01"][0]["L01F01"];
var test03 = obj["L01"][3]["L01L02"][0]["L01L02F01"];
I would like to know if somebody know any way to obtain the "path" of the test variables in this a way similar to:
GetPathOf(test01) => "F01"
GetPathOf(test02) => "L01[0].L01F01"
GetPathOf(test03) => "L01[3].L01L02[0].L01L02F01"
Thanks!

A Path property was added to JToken in release 5.0.1 (April 7, 2013) which does exactly what you describe.
So in your example you could simply write:
string path03 = test03.Path;
The path03 variable would then contain L01[3].L01L02[0].L01L02F01.
Fiddle: https://dotnetfiddle.net/5Dhc4i

Related

Azure REST API - Create, through programming, a database within an elasticPoll

I need to create, through programming, a database in an elasticPoll.
To do this, I'm using the API version 2014-04-01, indicated in "Azure REST APIs > SQL Database > Databases > Create Or Update".
I create a new HttpWebRequest object and launch the .Create() method
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Sql/servers/{2}/databases/{3}?api-version={4}", VariabiliGlobali.SubscriptionID, VariabiliGlobali.ResourceGroup, VariabiliGlobali.SqlServerName, databaseName, VariabiliGlobali.APIVersion));
and compile the properties:
request.Headers["Authorization"] = "Bearer" + token;
request.ContentType = "application/json; charset = utf-8";
request.Method = "PUT"
I create a new StreamWriter object
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
//streamWriter.Close();
}
and the .Write() mothod parameter, assign the complete Json code of the model shown in the "Databases - Create Or Update" example as below.
string json =
"{" +
"\"parameters\": {" +
"\"subscriptionId\": \"" + VariabiliGlobali.SubscriptionID + "\"," +
"\"resourceGroupName\": \"" + VariabiliGlobali.ResourceGroup + "\"," +
"\"serverName\": \"" + VariabiliGlobali.SqlServerName + "\"," +
"\"databaseName\": \"" + databaseName + "\"," +
"\"api-version\": \"" + VariabiliGlobali.APIVersion + "\"," +
"\"parameters\": {" +
"\"properties\": {" +
"\"elasticPoolName\": \"" + elasticPoolName + "\"" +
"}," +
"\"location\": \"West Europe\"" +
"}" +
"}," +
"\"responses\": {" +
"\"200\": {" +
"\"body\": {" +
"\"id\": \"/subscriptions/" + VariabiliGlobali.SubscriptionID + "/resourceGroups/" + VariabiliGlobali.ResourceGroup + "/providers/Microsoft.Sql/servers/" + VariabiliGlobali.SqlServerName + "/databases/" + databaseName + "\"," +
"\"name\": \"" + databaseName + "\"," +
"\"type\": \"Microsoft.Sql/servers/databases\"," +
"\"location\": \"West Europe\"," +
"\"kind\": \"v12.0,user\"," +
"\"properties\": {" +
"\"edition\": \"Standard\"," +
"\"status\": \"Online\"," +
"\"serviceLevelObjective\": \"S0\"," +
"\"collation\": \"SQL_Latin1_General_CP1_CI_AS\"," +
"\"creationDate\": \"2017-02-24T22:39:46.547Z\"," +
"\"maxSizeBytes\": \"268435456000\"," +
"\"currentServiceObjectiveId\": \"f1173c43-91bd-4aaa-973c-54e79e15235b\"," +
"\"requestedServiceObjectiveId\": \"f1173c43-91bd-4aaa-973c-54e79e15235b\"," +
"\"requestedServiceObjectiveName\": \"S0\"," +
"\"sampleName\": null," +
"\"defaultSecondaryLocation\": \"Japan West\"," +
"\"earliestRestoreDate\": \"2017-02-10T01:52:52.923Z\"," +
"\"elasticPoolName\": null," +
"\"containmentState\": 2," +
"\"readScale\": \"Disabled\"," +
"\"failoverGroupId\": null" +
"}" +
"}" +
"}," +
"\"201\": {" +
"\"body\": {" +
"\"id\": \"/subscriptions/" + VariabiliGlobali.SubscriptionID + "/resourceGroups/" + VariabiliGlobali.ResourceGroup + "/providers/Microsoft.Sql/servers/" + VariabiliGlobali.SqlServerName + "/databases/" + databaseName + "\"," +
"\"name\": \"" + databaseName + "\"," +
"\"type\": \"Microsoft.Sql/servers/databases\"," +
"\"location\": \"West Europe\"," +
"\"kind\": \"v12.0,user\"," +
"\"properties\": {" +
"\"edition\": \"Standard\"," +
"\"status\": \"Online\"," +
"\"serviceLevelObjective\": \"S0\"," +
"\"collation\": \"SQL_Latin1_General_CP1_CI_AS\"," +
"\"creationDate\": \"2017-02-24T22:39:46.547Z\"," +
"\"maxSizeBytes\": \"268435456000\"," +
"\"currentServiceObjectiveId\": \"f1173c43-91bd-4aaa-973c-54e79e15235b\"," +
"\"requestedServiceObjectiveId\": \"f1173c43-91bd-4aaa-973c-54e79e15235b\"," +
"\"requestedServiceObjectiveName\": \"S0\"," +
"\"sampleName\": null," +
"\"defaultSecondaryLocation\": \"Japan West\"," +
"\"earliestRestoreDate\": \"2017-02-10T01:52:52.923Z\"," +
"\"elasticPoolName\": null," +
"\"containmentState\": 2," +
"\"readScale\": \"Disabled\"," +
"\"failoverGroupId\": null" +
"}" +
"}" +
"}," +
"\"202\": { }" +
"}" +
"}";
Launch the .GetResponse() method of the HttpWebRequest object
var httpResponse = (HttpWebResponse)request.GetResponse();
and in response I get the following error:
{'Error': {"code": "InvalidRequestContent", "message": "The request content was invalid and could not be deserialized: 'Could not find member' parameters on object of type 'ResourceDefinition' , Line 1, position 14. '. "}}
Where am I wrong?
Thanks in advance.
I believe the documentation is incorrect. Correct request payload should be:
{"properties": {"elasticPoolName": "XXXXX"},"location": "West Europe"}

C# - How to detect browser type

I'm running Selenium with C# for my automation testing on multiple browsers (IE, FF, Chrome) and there is one part of my test that passes for Chrome but not Firefox.
Is there a way to detect the browser type that is currently being used during the automated test?
You can install UAParser from Nugget :
https://www.nuget.org/packages/UAParser/
It will read the client header and Parse it.
Exemple:
//string uaString = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3";
// Request the header
string uaString= HttpContext.Current.Request.UserAgent.ToString();
// get a parser with the embedded regex patterns
var uaParser = Parser.GetDefault();
// get a parser using externally supplied yaml definitions
// var uaParser = Parser.FromYamlFile(pathToYamlFile);
// var uaParser = Parser.FromYaml(yamlString);
ClientInfo c = uaParser.Parse(uaString);
Console.WriteLine(c.UserAgent.Family); // => "Mobile Safari"
Console.WriteLine(c.UserAgent.Major); // => "5"
Console.WriteLine(c.UserAgent.Minor); // => "1"
Console.WriteLine(c.OS.Family); // => "iOS"
Console.WriteLine(c.OS.Major); // => "5"
Console.WriteLine(c.OS.Minor); // => "1"
Console.WriteLine(c.Device.Family); // => "iPhone"
Use the following code
System.Web.HttpBrowserCapabilities browser = Request.Browser;
string s = "Browser Capabilities\n"
+ "Type = " + browser.Type + "\n"
+ "Name = " + browser.Browser + "\n"
+ "Version = " + browser.Version + "\n"
+ "Major Version = " + browser.MajorVersion + "\n"
+ "Minor Version = " + browser.MinorVersion + "\n"
+ "Platform = " + browser.Platform + "\n"
+ "Is Beta = " + browser.Beta + "\n"
+ "Is Crawler = " + browser.Crawler + "\n"
+ "Is AOL = " + browser.AOL + "\n"
+ "Is Win16 = " + browser.Win16 + "\n"
+ "Is Win32 = " + browser.Win32 + "\n"
+ "Supports Frames = " + browser.Frames + "\n"
+ "Supports Tables = " + browser.Tables + "\n"
+ "Supports Cookies = " + browser.Cookies + "\n"
+ "Supports VBScript = " + browser.VBScript + "\n"
+ "Supports JavaScript = " +
browser.EcmaScriptVersion.ToString() + "\n"
+ "Supports Java Applets = " + browser.JavaApplets + "\n"
+ "Supports ActiveX Controls = " + browser.ActiveXControls
+ "\n"
+ "Supports JavaScript Version = " +
browser["JavaScriptVersion"] + "\n";

C# take output and put it into CSV file

I have some code that is currently doing the following at the end of the code:
Console.WriteLine(vid.totalCurrentCharges + " : " + vid.assetId + " : " + vid.componentName + " : " + vid.recurringCharge);
Console.readline().
I need to take the output of vid.totalCurrentCharges + " : " + vid.assetId + " : " + vid.componentName + " : " + vid.recurringCharge, and write It to a csv file. Can someone here help with this? Currently all it is doing is writing the output to console.
Instead of Console.Writeline you need to create StreamWriter. Just like this:
using (StreamWriter writer = new StreamWriter("important.csv"))
{
//probably a loop here
writer.WriteLine(vid.totalCurrentCharges + " , " + vid.assetId + " , " + vid.componentName + " , " + vid.recurringCharge);
}
Moreover you can use String.Join to concatenate strings instead of "adding" them, so above WriteLine can be converted into:
writer.WriteLine(String.Join(",", vid.totalCurrentCharges, vid.assetId, vid.componentName, vid.recurringCharge));

Multiple Google maps on single page

I would like to add multiple maps of the Google Maps API to a page of my C# ASP.NET application. However, with my current code, only the last map is shown. All the other divs that should contain a map are empty. As you can see in my code, the maps already have unique names (not on a nice way, but it is unique). Can someone explain what I am doing wrong?
It would be really appreciated.
Initialize Google:
protected void loadGoogle()
{
var googleScript = "function loadScript() {" +
"var script = document.createElement(\"script\");" +
"script.type = \"text/javascript\";" +
"script.src = \"http://maps.google.com/maps/api/js?sensor=false& callback=initialize\"; " +
"document.body.appendChild(script);" +
"}" +
"window.onload = loadScript;";
ClientScript.RegisterStartupScript(typeof(Page), "CreateGoogleMapScript", googleScript, true);
}
Create maps (called multiple times):
protected void createMap(String mapId, String address)
{
var script = "function initialize() {" +
"var geocoder = new google.maps.Geocoder();" +
"var latlng = new google.maps.LatLng(-34.397, 150.644);" +
"var mapOptions" + mapId + " = {" +
"zoom: 16," +
"center: latlng," +
"mapTypeId: google.maps.MapTypeId.ROADMAP" +
"};" +
" var map" + mapId + " = new google.maps.Map(document.getElementById(" + mapId + "), mapOptions" + mapId + ");" +
"var address = \"" + address + "\";" +
"geocoder.geocode( { 'address': address}, function(results, status) {" +
"if (status == google.maps.GeocoderStatus.OK) {" +
"map" + mapId + ".setCenter(results[0].geometry.location);" +
"var marker = new google.maps.Marker({" +
"map: map" + mapId + "," +
"position: results[0].geometry.location" +
"});" +
"} else {" +
"alert(\"Geocode was not successful for the following reason: \" + status); " +
"}" +
"});" +
"}";
ClientScript.RegisterClientScriptBlock(typeof(Page), "CreateMapScript"+mapId, script, true);
}
Called by:
While loop, with a literal.Text that adds a new div, followed by createMap(mapId, address);
UPDATE:
My new code:
var script = "function initialize() { var geocoder = new google.maps.Geocoder();";
for (int i = 0; i < maps.Count; i++)
{
String currentId = maps[i] as String;
String currentLocation = locations[i] as String;
script += " " +
"var latlng = new google.maps.LatLng(" + 500 + "," + 400 + ");" +
"var myOptions = {" +
"zoom: 16," +
"center: latlng," +
"mapTypeId: google.maps.MapTypeId.ROADMAP" +
"};" +
"var map = new google.maps.Map(document.getElementById(\"" + currentId + "\"), myOptions);" +
"var address = \"" + currentLocation + "\";" +
"geocoder.geocode( { 'address': address}, function(results, status) {" +
"if (status == google.maps.GeocoderStatus.OK) {" +
"map.setCenter(results[0].geometry.location);" +
"var marker = new google.maps.Marker({" +
"map: map," +
"position: results[0].geometry.location" +
"});" +
"} else {" +
"alert(\"Geocode was not successful for the following reason: \" + status); " +
"}" +
"});";
}
script += "};";
Now all maps are drawn, but only the last map has the right location. The other ones are based on the latlng variable. Why can't the geocoder be used multiple times?
Perhaps just the last initialize function is firing in the browser? Try having just 1 initialise function that initialises all your maps.

Why the following Conditional Operator works strangely in StringBuilder containing Nullable type? in C#?

StringBuilder htmlResp=new StringBuilder();
int? cuID= 1;
string cuName="Tom";
string cuEmpID="ZXCV";
htmlResp .Append( "<option value=\"" + cuID.Value + "\">" + cuName+" ("+cuEmpID==""? "-":cuEmpID+")"+ "</option>");
html.Resp.ToString();
I cannot understand why the above code(modified from the actual codes) always gives me weird result:"ZXCV)" instead of "Tom (ZXCV)".
Does anybody knows the reason behind and can provide a reference if possible?
You are missing some brackets around your conditional expression.
Try this instead:
string text = "<option value=\"" + cuID.Value + "\">" + cuName + " (" + (cuEmpID == "" ? "-" : cuEmpID) + ")" + "</option>";
htmlResp.Append(text);
As to why the missing brackets caused that to happen... That's an interesting question!
To answer it, let me simplify the original code a bit:
string text = ">>>" + cuEmpID == "" ? "-" : cuEmpID + "<<<"; // Gives "ZXCV<<<"
What's happening is that the conditional expression is using ">>>" + cuEmpID == "" as the condition. This is not equal to "" so the right-hand side of the conditional expression is used, namely the cuEmpID + "<<<" part, which gives the output we're seeing.
You should really simplify the expression, for example:
string normalisedEmpID = cuEmpID == "" ? "-" : cuEmpID;
string text = string.Format
(
"<option value=\"{0}\">{1} ({2})</option>",
cuID.Value,
cuName,
normalisedEmpID
);
A good example of "don't make expressions too complex".
"<option value=\"" + cuID.Value + "\">" + cuName
+ " ("+cuEmpID==""? "-":cuEmpID+")"+ "</option>");
is compiled as
("<option value=\"" + cuID.Value + "\">" + cuName+" ("+cuEmpID ) == ""
? "-"
: cuEmpID+")"+ "</option>");
A simple 'fix' would be
"<option value=\"" + cuID.Value + "\">" + cuName + " ("
+ ((cuEmpID == "") ? "-" : cuEmpID )
+ ")" + "</option>"
but for readability, use some intermediate variables. ?: should never be nested inside other expressions.

Categories

Resources