Debugger blows up in JsonElement.DebuggerDisplay.get - .net-core

I'm writing my first project trying to use System.Text.Json in a .net core app. I'm getting a jsonl file with a particular structure, and my requirements are in effect to UNPIVOT/flatten an array of child objects in one object into a stream of transformed objects.
It was going fine until I put a breakpoint on the routine doing the UNPIVOT and the debugger itself started blowing up with an access violation in JsonElement.DebuggerDisplay.get. Interestingly,
a) it floats around which row it blows up on and b) it seems to be somewhat dependent on how long I wait before clicking Continue. In other words, if I wait a couple of seconds, it seems to work; if I click right away it blows up faster.
Just wondering if anyone else had run into something like this. And whether I should just switch back to NewtonSoft to avoid the headache.
Here's what my code looks like:
public static IEnumerable<MyResult> ConvertJson(JsonElement input)
{
JsonElement transformArray, base_url;
if (!input.TryGetProperty("child_objects", out transformArray) || transformArray.ValueKind != JsonValueKind.Array)
yield break;
if (!input.TryGetProperty("base_url", out base_url) || base_url.ValueKind != JsonValueKind.String)
yield break;
int i = 0;
foreach(var o in transformArray.EnumerateArray())
{
// Break point on line below. Click Continue too quickly, and I get DebuggerDisplay.get access violation
var result = new MyResult();
result.BaseURL = base_url.ToString();
result.PageID = i; i++;
JsonElement prop;
if (o.TryGetProperty("prop1", out prop) && prop.ValueKind == JsonValueKind.String) result.Prop1 = prop.ToString();
if (o.TryGetProperty("text", out prop) && prop.ValueKind == JsonValueKind.String) result.Text = prop.ToString();
if (o.TryGetProperty("language", out prop) && prop.ValueKind == JsonValueKind.String) result.Language = prop.ToString();
yield return result;
}
}
and it's called like this:
string l = JsonlStream.ReadLine();
var json = JsonSerializer.Deserialize<JsonElement>(l);
foreach (var i in ConvertJson(json))
{
...
}

Related

Project to a Known Type using Simple.OData.Client Dynamic Syntax

Simple.OData.Client has a typed and dynamic (and basic) syntax.
I like the typed, but I don't want to build out all my types. In the end I really only need two or so types in the results I get.
But my queries need more types to properly filter the results.
So I want to use the dynamic syntax. But I want to cast the results to classes I have.
I can easily do this manually, but I thought I would see if Simple.OData.Client supports this before I go writing up all that conversion code for each query.
Here is some dynamic syntax code that runs without errors:
client.For(x.Client).Top(10).Select(x.ClientId, x.Name).FindEntriesAsync();
Here is an example of what I had hoped would work (selecting into a new Client object)
client.For(x.Client).Top(10).Select(new Client(x.ClientId, x.Name)).FindEntriesAsync();
But that kind of projection is not supported (I get an "has some invalid arguments" error).
Is there a way to support projection into an existing class when using the dynamic syntax of Simple.OData.Client?
EDIT: The code below works. But it's performance is terrible. I decided to abandon it and write hand written mappers for each type I needed.
This is what I came up with:
dynamic results = oDataClient.For(x.Client).Select(x.ClientId, x.Name).FindEntriesAsync().Result;
var listOfClients = SimpleODataToList<Client>(results);
public List<T> SimpleODataToList<T>(dynamic sourceObjects) where T : new()
{
List<T> targetList = new List<T>();
foreach (var sourceObject in sourceObjects)
{
// This is a dictionary with keys (properties) and values. But no
// matter what sourceObject is passed in, the values will always be
// the values of the first entry in the sourceObjects list.
var sourceProperties = ((System.Collections.Generic.IDictionary<string, object>)sourceObject);
var targetProperties = typeof(Client).GetProperties().Where(prop => prop.CanWrite);
var targetObject = new T();
foreach (var targetProperty in targetProperties)
{
if (sourceProperties.ContainsKey(targetProperty.Name))
{
var sourceValue = GetProperty(sourceObject, targetProperty.Name);
targetProperty.SetValue(targetObject, sourceValue, null);
}
}
targetList.Add(targetObject);
}
return targetList;
}
public static object GetProperty(object o, string member)
{
if (o == null) throw new ArgumentNullException("o");
if (member == null) throw new ArgumentNullException("member");
Type scope = o.GetType();
IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
if (provider != null)
{
ParameterExpression param = Expression.Parameter(typeof(object));
DynamicMetaObject mobj = provider.GetMetaObject(param);
GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) });
DynamicMetaObject ret = mobj.BindGetMember(binder);
BlockExpression final = Expression.Block(
Expression.Label(CallSiteBinder.UpdateLabel),
ret.Expression
);
LambdaExpression lambda = Expression.Lambda(final, param);
Delegate del = lambda.Compile();
return del.DynamicInvoke(o);
}
else
{
return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
}
}
It was made much harder because normal casts and such for the dynamic objects returned would only give the first object in the list over and over. The GetProperty method works around this limitation.

What could be reasons for this android EditText control to convert the input to the ascii sequence

So for some project i'm working with Xamarin.Forms.
Since one area is just unbearably slow with Xamarin.Forms i've used a CustomRenderer to solve one particular area where a list is involved.
After getting back to the project and upgrading packages, i've suddenly got the weirdest bug.
I am setting "1234" to an EditText, and the EditText.Text Property is suddenly "49505152" - the string is converted to its ascii equivalent.
Is this a known issue? Does anyone know how to fix it?
The cause of the issue was that my EditText had an InputFilter applied and that after updating a package suddenly another code path of FilterFormatted was executed.
public ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
{
var startSection = dest.SubSequenceFormatted(0, dstart);
var insert = source.SubSequenceFormatted(start, end);
var endSection = dest.SubSequenceFormatted(dstart, dest.Length());
var merged = $"{startSection}{insert}{endSection}";
if (ValidationRegex.IsMatch(merged) && InputRangeCheck(merged, CultureInfo.InvariantCulture))
{
StringBuilder sb = new StringBuilder(end - start);
for (int i = start; i < end; i++)
{
char c = source.CharAt(i);
sb.Append(c);
}
if (source is ISpanned) {
SpannableString sp = new SpannableString(sb);
TextUtils.CopySpansFrom((ISpanned)source, start, sb.Length(), null, sp, 0);
return sp;
} else {
// AFTER UPDATE THIS PATH WAS ENTERED UNLIKE BEFORE
return sb;
}
}
else
{
return new SpannableString(string.Empty);
}
}

Dictionary Syntax Error in Google Apps Script

I have a function that creates a dictionary based on a series of values from a sheet. I then try to pull one of the values from that sheet using a key. It works fine to log to the console. However, in an if statement, it says syntax error and nothing else. I cannot figure it out. Here is the function and the code that crashes. This problem only occurs in the for loop, and does not occur outside of it.
//creates dictionary
function columnLocationWithNotation(notation) {
var spreadsheet = SpreadsheetApp.openByUrl();
var sheet = spreadsheet.getActiveSheet();
var data = sheet.getDataRange();
var cells = data.getValues();
var dictionary = {};
switch (notation) {
case "zeroIndex":
for (var i = 0; i < sheet.getLastRow(); i++) {
dictionary[cells[i][0]] = cells[i][1]
}
return dictionary
break;
case "regularIndex":
for (var i = 0; i < sheet.getLastRow(); i++) {
dictionary[cells[i][0]] = cells[i][2]
}
return dictionary
break;
case "string":
for (var i = 0; i < sheet.getLastRow(); i++) {
dictionary[cells[i][0]] = cells[i][3]
}
return dictionary
break;
}
}
var master0indexDictionary = columnLocationWithNotation("zeroIndex")
for (var i = 1; i =< (sheet.getLastRow() - 1); i++) {
var phone = master0indexDictionary["Tutor Name"]
if (cells[i][phone] === phoneNumber) { //LINE WITH SYNTAX ERROR
//do something
}
It's not the highlighted line that is causing the problem, even though there are many other issues with your script. There's no '=<' operator in JavaScript. Use '<=' instead:
for (var i = 1; i <= (sheet.getLastRow() - 1); i++) {
Also, as Tanaike pointed out, your 'cells' variable is only defined in the context of your 'columnLocationWithNotation(notation)' function and will not be accessible from the global context. Globally-defined variables are visible from the functions you declare inside the global object, but not vice versa. Same applies to the 'sheet' variable. The 'phoneNumber' variable doesn't seem to be defined, at least not in the snippet of code you provided.
Note that putting 'break' after 'return' statements is redundant.
return dictionary;
break;
You can just return out of 'switch' statement without using breaks, or leave the breaks and put a single 'return' statement after 'switch'.
Finally, always put a semicolon at the end of the line. Doing so will help you avoid many potential pitfalls and issues with JS parser. I noticed several instances where you omitted the semicolon:
return dictionary
break;
var phone = master0indexDictionary["Tutor Name"]
For example, the following code will break if you don't have a habit of putting the semicolon in its rightful place
var a = {name: 'John'} //no semicolon
[a].forEach(function(element) {
Logger.log(element); //logs undefined
})
The JS parser treats this code as one line, so 'a' will still be 'undefined' by the time you call the 'forEach()' loop on the array.

how to handle this type of things. using asp.net mvc

I have
public jsonresult update(studentinfo s)
{
for(i=0;i>0;i++)
{
var x = // i am getting some x so i am checking again
if( x != null)
{
var updateuser = student.update(s.student,"","");
**return json(updateuser.ToString());** // if i keep it here i am getting exceptoin saying not all code paths return value bec this return i can not keep it out for loop bec each and evary updateuser i need to return json..
}
}
}
How to overcome this type of things?
What language are you using to write your code? What you've posted doesn't look like any of the valid languages I know for .NET. Here's how the controller action might look in C# (assuming this is the language you are using):
public ActionResult Update(StudentInfo s)
{
// create some collection that will contain all updated users
var updatedUsers = new List<StudentInfo>();
// Revise the loop as it is absolutely not clear from your code
// what you are trying to do. The way you wrote the loop it will
// never execute - for(int i=0; i>0; i++)
for (int i = 0; i < 5; i++)
{
var updatedUser = student.Update(s.student, "", "");
updatedUsers.Add(updatedUser);
}
// return the list of updated users outside the loop so that the compiler
// doesn't complain about paths of the method not returning a value
return Json(updatedUsers);
}
If I understand correctly, you want to return a collection of users. The 'return' keyword does not work like that. You need to return the entire collection at once.

ASP.Net Webforms w/ AJAX Slow Rendering

I have a Webforms, AJAX-enabled web page which, when rendering large amounts of data, is extremely slow to load in IE (we're married to IE - no other browser options). In an attempt to determine the source of the slowness, I viewed the HTML source (about 2.5 MB) and copied all of it (except for the Ajax JavaScript calls) to a blank .html file. IE renders this file MUCH faster than when the rendering happens through .Net. This seems to indicate that the AJAX JavaScript is slowing down the display of the page. Does this sound plausible? Any recommendations on improving performance here?
I've already eliminated as many UpdatePanel controls as I can from the page, but it doesn't seem to help with render time.
Thanks for the help!
Update... In the HTML source, I noticed that at the bottom of the screen, a call to WebForm_InitCallback() appears. When I executed this call directly through javascript:alert(WebForm_InitCallback());, the CPU spikes for 12 seconds before it completes! This call is here because I implemented ICallbackEventHandler to try to accomplish some traditional-style AJAX handling. Looking at WebResource.axd, that WebForm_InitCallback() method iterates through the entire form and attaches some kind of events to EVERY SINGLE textbox, checkbox, radiobutton, etc. So I guess I really need to abandon ScriptManager and UpdatePanel altogether here. Poop.
Andy
I hate to say this, but can you take the Microsoft AJAX out of the equation? Try it with doing an XMLHTTP request and populate the data yourself. That way at least you could step through the js and figure out if it is time on the server, time turning the resulting XML or JSON into an object, or time spent populating your data on screen.
This is an old topic but I thought I should share what I recently did to fix long running script error in IE 7 caused by WebForm_InitCallback.
I had a page with over 2000 form elements and in IE 7 was causing a long running script warning / browser freeze for a client. We have other pages with many more form elements and paging or other options aren't options due to needing a quick turn around to improve performance.
I narrowed it down to WebForm_InitCallback, and even further to the following line:
element = theForm.elements[i];
By saving a reference to theForm.elements instead and using it to access the index, I found significant performance gains.
var elements = theForm.elements;
for (var i = 0; i < count; i++) {
element = elements[i];
....
}
I made a jsperf to test the difference since I didn't expect such impressive gains from not calling the refinement every time.
Beyond that, I found better performance by replacing the concatenation in WebForm_InitCallbackAddField to adding the strings to an array and joining it together after the for loop in WebForm_InitCallback completes and saving it back into __theFormPostData.
Here are the original two function that you'll see in the WebResource:
function WebForm_InitCallback() {
var count = theForm.elements.length;
var element;
for (var i = 0; i < count; i++) {
element = theForm.elements[i];
var tagName = element.tagName.toLowerCase();
if (tagName == "input") {
var type = element.type;
if ((__callbackTextTypes.test(type) || ((type == "checkbox" || type == "radio") && element.checked))
&& (element.id != "__EVENTVALIDATION")) {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
else if (tagName == "select") {
var selectCount = element.options.length;
for (var j = 0; j < selectCount; j++) {
var selectChild = element.options[j];
if (selectChild.selected == true) {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
}
else if (tagName == "textarea") {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
}
function WebForm_InitCallbackAddField(name, value) {
var nameValue = new Object();
nameValue.name = name;
nameValue.value = value;
__theFormPostCollection[__theFormPostCollection.length] = nameValue;
__theFormPostData += WebForm_EncodeCallback(name) + "=" + WebForm_EncodeCallback(value) + "&";
}
And here is the javascript I added to my page to overwrite them. It's important that this code is inserted after the WebResource is added and before WebForm_InitCallback is called.
var __theFormPostDataArr = [];
if (typeof (WebForm_InitCallback) != "undefined") {
WebForm_InitCallback = function () {
var count = theForm.elements.length;
var element;
var elements = theForm.elements;
for (var i = 0; i < count; i++) {
element = elements[i];
var tagName = element.tagName.toLowerCase();
if (tagName == "input") {
var type = element.type;
if ((type == "text" || type == "hidden" || type == "password" ||
((type == "checkbox" || type == "radio") && element.checked)) &&
(element.id != "__EVENTVALIDATION")) {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
else if (tagName == "select") {
var selectCount = element.options.length;
for (var j = 0; j < selectCount; j++) {
var selectChild = element.options[j];
if (selectChild.selected == true) {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
}
else if (tagName == "textarea") {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
__theFormPostData = __theFormPostDataArr.join('');
}
WebForm_InitCallbackAddField = function (name, value) {
__theFormPostDataArr = [];
var nameValue = new Object();
nameValue.name = name;
nameValue.value = value;
__theFormPostCollection[__theFormPostCollection.length] = nameValue;
__theFormPostDataArr[__theFormPostDataArr.length] = WebForm_EncodeCallback(name);
__theFormPostDataArr[__theFormPostDataArr.length] = "=";
__theFormPostDataArr[__theFormPostDataArr.length] = WebForm_EncodeCallback(value);
__theFormPostDataArr[__theFormPostDataArr.length] = "&";
}
}
Ultimately, it took the run time of WebForm_InitCallback from 27 seconds to 4 seconds on my IE 7 machine.

Resources