PuppeteerSharp evaluate expression to complex type? - c#

Hi I am using PuppeteerSharp for the first time and am wondering if EvaulateExpressionAsync supports a way to convert to a complex c# object. So when i try to do something like this:
var allResultsSelector = ".sortableTable.resultTable tr.studyResultRow";
var jsSelectAllAnchors = $"Array.from(document.querySelectorAll('{allResultsSelector}')).map(f=>f.innerText);";
await frmSearch.WaitForSelectorAsync(allResultsSelector);
var urls = await frmSearch.EvaluateExpressionAsync<InteleStudyResult[]>(jsSelectAllAnchors);
c# type for now
public class InteleStudyResult
{
public string PatientName { get; set; }
//public string PatientId { get; set; }
//public DateTime DOB { get; set; }
//public string Sex { get; set; }
//public string Accession { get; set; }
//public DateTime StudyDate { get; set; }
//public string Modality { get; set; }
//public int? Series { get; set; }
//public string StudyDescription { get; set; }
}
exception occurs on the Eval call
Newtonsoft.Json.JsonSerializationException
HResult=0x80131500
Message=Error converting value " my string here " to type 'InteleradWebAccessor.InteleStudyResult'. Path '[0]'.
Source=Newtonsoft.Json
Inner Exception 1:
ArgumentException: Could not cast or convert from System.String to InteleradWebAccessor.InteleStudyResult.
If this is not supported I'd greatly appreciate a suggestion on best way to handle getting what is a html table row into a c# complex type using PuppeteerSharp

You should an object in your map
Array.from(document.querySelectorAll('{allResultsSelector}'))
.map(f =>{ return { patientName: f.innerText} });

Related

Migrate from Microsoft.WindowsAzure.Storage.Table to Azure.Data.Tables - deserialization issues

I'm in the process of migrating code from Microsoft.WindowsAzure.Storage.Table to the Azure.Data.Tables. The issue described appears on querying entities with content that don't match the datatype. Consider the following snippet of migrated code:
public class WorkstationInfoTableEntity : Azure.Data.Tables.ITableEntity
{
//ITableEntity
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
//
public byte[] Documents { get; set; }
public DateTime? MyDocumentsLastRestoreDate { get; set; }
public DateTime? MyDocumentsModifiedOn { get; set; }
....
//
}
var table = tableServiceClient.GetTableClient(CloudTableNames.Workstations);
var workstations = table.Query<WorkstationInfoTableEntity>(c => c.PartitionKey == customerId);
var results = workstations.OrderBy(c => c.Name).ToArray();
If the table contains an entity that holds some string: "[RME]" (any non base64 string) in the Documents column then the Query will fail complaining that :
"System.FormatException: 'The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."
because it expects a base64 string but the value is just some string.
Or if the MyDocumentsModifiedOn column contains some empty string inside then the query crashes with the error:
"System.FormatException: 'String was not recognized as a valid DateTime."
The Microsoft.WindowsAzure.Storage.Table library would have populated the property with a null value if a deserialization problem had occurred.
Expected are a list of entities whose properties that failed being deserialized are set to null.
Actual behavior: the code crashes
Is there any way to prevent crashing if any deserialization issue appeared ?
Right now, it is imposible to correct those entities.
So this is more of a workaround since you can't update update all of the empty MyDocumentsModifiedOn to DateTime.MinValue.
public class WorkstationInfoTableEntity : Azure.Data.Tables.ITableEntity
{
//ITableEntity
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
//
public byte[] Documents { get; set; }
public DateTime? MyDocumentsLastRestoreDate { get; set; }
public DateTime? _MyDocumentsModifiedOn { get; set; }
public string? MyDocumentsModifiedOn
{
get
{
return _MyDocumentsModifiedOn.ToString() // Or whatever format you need
}
set
{
if(!Value.HasValue)
{
_MyDocumentsModifiedOn = DateTime.MinValue;
}
else if(Value.Value == "")
{
_MyDocumentsModifiedOn = DateTime.MinValue;
}
else
{
DateTime TempDate;
if(DateTime.TryParse(Value.Value, out TempDate))
{
_MyDocumentsModifiedOn = TempDate
}
else
{
_MyDocumentsModifiedOn = DateTime.MinValue;
}
}
}
}
....
//
}
You will have to use _MyDocumentsModifiedOn to get the datetime. Not an amazing solution but it'll work.

C# Searching List of Arrays for specific value and returning related value

I hope this isn't a foolishly simple question. Im very simply trying to figure out how to manipulate a relatively simple table in SQLite through C#.
Im looking to take a parameter and search a List of Arrays for one such array where the parameter matches, and return a related variable within that same array.
For example where an array in the list might be.
Name IATA
Brisbane BNE
The sqlbind:
public static List<Airport> LoadAirports()
{
using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
{
var output = cnn.Query<Airport>("select * from Airport", new DynamicParameters());
return output.ToList();
}
}
The Class:
class Airport
{
int Id { get; set; }
string Name { get; set; }
string LocationName { get; set; }
string IATA { get; set; }
string PortType { get; set; }
string PortOwner { get; set; }
string MotherPort { get; set; }
bool Active { get; set; }
bool IsApplyMeetAndGreet { get; set; }
decimal MeetAndGreet { get; set; }
}
The main Program:
List<Airport> Airports = new List<Airport>();
public FreightCalculator()
{
LoadAirportsList();
string OriginName = OriginInput.Value;
var OriginAirport = Airports.Where(s => s.Name == OriginName);
}
private void LoadAirportsList()
{
Airports = SqliteDataAccess.LoadAirports();
}
Ive tried various combinations of Where, Equals, For each indexing etc. Always getting an error of some kind.
The Error with the above Airports.Where is that the s.Name is inaccessible due to its protection level.
If I do:
var OriginAirport = Airports.Where(Name => Name == OriginName);
I get an error where the operand == cannot be used with Airport and String (Though Name is a string in Airport.)
Im either missing something simple or making this more complicated than it needs to be. Once I find the matching Airport, I need to return the IATA code.
Which I envisage looking like this:
var OriginIATA = OriginAirport.IATA;
Im tired and feeling dumb. Please help :(
Since you declared all members of the Airport class as properties I assume you wanted to expose them publicly.
The error you get is because they are private members and can't be accessed outside the class.
Change "Airport" class to:
class Airport
{
public int Id { get; set; }
public string Name { get; set; }
public string LocationName { get; set; }
public string IATA { get; set; }
public string PortType { get; set; }
public string PortOwner { get; set; }
public string MotherPort { get; set; }
public bool Active { get; set; }
public bool IsApplyMeetAndGreet { get; set; }
public decimal MeetAndGreet { get; set; }
}

Convert JSON string to object C#

I have JSON string results as follows.
In this response Sometimes sizeKey and sizeName properties are returned as a string. But sometimes both properties are returns inside an array as follows
I am using following code to convert it to object
var assets = jObject["assets"].Children().ToList();
foreach (var item in assets)
{
decorationAssets.Add(item.ToObject<AEDecorationAssets>());
}
And my AEDecorationAssets class is as follows.
public class AEDecorationAssets
{
public string Id { get; set; }
public string Url { get; set; }
public string[] Colors { get; set; }
public string FontKey { get; set; }
public string SizeKey { get; set; }
public string ViewKey { get; set; }
public string FontName { get; set; }
public int Rotation { get; set; }
public string SizeName { get; set; }
public string TextValue { get; set; }
public string EntityType { get; set; }
public string LocationCode { get; set; }
public string LocationName { get; set; }
public string TextEffectKey { get; set; }
public string TextEffectName { get; set; }
public string DecorationMethod { get; set; }
public string NumDecorationColors { get; set; }
}
At the time when "sizeKey" is an array, the above code gives an error. How can I resolve this issue? Is there any JSON property we can use to resolve it?
One way you can do it is by making your SizeKey type an object (i.e. public object SizeKey { get; set; }), then you can switch/case on item.ToObject<AEDecorationAssets>().SizeKey.GetType() to figure out how to handle it (i.e. if String do this, if JArray do that), etc.
If a JSON type is sometime an array, and sometimes a string, you can't really map it simply to a .NET type, as there is none that supports this behavior.
So first you need a datatype that can store this, like and string[] or List<string>.
It could be that JsonConvert will solve this automatically, but otherwise you'll need to write a custom ContractResolver or JsonConverter. Here you can detect if the source property is a string or array. If it's an array, you can use the default deserialization. If it is a string, you need to convert it to an array with a single value.
Simply get json result for which you want to create c# object and then you can valid json response from https://jsonlint.com/ and then you can create c# object of any type json response which you want through http://json2csharp.com. And after get c# object of your json response you only need to deserialization of your json response to c# object which you have created. which will return you expected result.

Specified cast is not valid in ASP.NET? [duplicate]

This question already has answers here:
"Specified cast is not valid" error in C# windows forms program
(9 answers)
Closed 6 years ago.
I got the following code:
var model = new List<LogModels>();
while (reader.Read())
{
var logContent = new LogModels(
(int)reader["id"],
(string)reader["response"],
(string)reader["language"],
(string)reader["country"],
(string)reader["location"],
(string)reader["os"],
(string)reader["browser"],
(string)reader["type"],
(DateTime)reader["date"]
);
model.Add(logContent);
}
But I get the following error:
An exception of type 'System.InvalidCastException' occurred in Speed Services.dll but was not handled in user code
Additional information: Specified cast is not valid.
Image: https://i.gyazo.com/adf04b8e271bb53c93303d5774a48f80.png
My model (LogModels) looks like this:
public int id { get; set; }
public string response { get; set; }
public string language { get; set; }
public string country { get; set; }
public string location { get; set; }
public string os { get; set; }
public string browser { get; set; }
public string type { get; set; }
public DateTime date { get; set; }
Does someone know what the issue could be since I can't seem to find the problem?
var model = new List<LogModels>();
while (reader.Read())
{
var logContent = new LogModels(
Convert.ToInt32(reader["id"].Tostring()),
(string)reader["response"],
(string)reader["language"],
(string)reader["country"],
(string)reader["location"],
(string)reader["os"],
(string)reader["browser"],
(string)reader["type"],
Convert.ToDateTime(reader["date"].Tostring())
);
model.Add(logContent);
}
casting problem because of integer or datetime value.
(int)reader["Id"] instead of Convert.ToInt32(reader["Id"].Tostring())
(DateTime)reader["date"] instead of Convert.ToDateTime(reader["date"].Tostring())

How to convert JSON Array to List<>?

This is my json and I need to access the values under each object in the attendance array:
{"name":" ","course":"","attendance":[{"name":"INTERNATIONAL FINANCE","type":"Theory","conducted":"55","present":"50"},{"name":"INDIAN CONSTITUTION","type":"Theory","conducted":"6","present":"6"}]}
Here is my code:
public class Att
{
public class Attendance
{
public string name { get; set; }
public string type { get; set; }
public string conducted { get; set; }
public string present { get; set; }
}
public Att(string json)
{
JObject jObject = JObject.Parse(json);
JToken jUser = jObject;
name = (string)jUser["name"];
course = (string)jUser["course"];
attender = jUser["attendance"].ToList<Attendance>;
}
public string name { get; set; }
public string course { get; set; }
public string email { get; set; }
//public Array attend { get; set; }
public List<Attendance> attender { get; set; }
}
It is the attender = jUser["attendance"].ToList<Attendance>; line that I have a problem with. It says,
Cannot convert method group ToList to non-delegate type. Did you intend to invoke this method?
How do I access those values?
You have a typo!
attendance vs attendence
And this should work
attender = jUser["attendance"].ToObject<List<Attendance>>();
You may find the running result at DotNetFiddle
You wanted to write:
attender = jUser["attendence"].ToList<Attendance>(); // notice the ()
About the Error:
When you dont put the parantheses there, C# assumes you want
to assign the function (delegate) ToList to the varaible attender, instead of
invoking it and assign its return value.

Categories