Deserialize the EventValidation object - c#

I am trying to serialize and deserialize the event validation store. I have used code on MSDN to do the same with the viewstate. I cannot seem to get the data out of the EventValidation object.
System.Web.UI.LosFormatter los = new System.Web.UI.LosFormatter();
var t = los.Deserialize("/wEdAAXD48AAvF6Ff7P5UOQbT3VqkrDKlMWdnNXfGOHHYL4xn7VF+rYDddmo2pWyOYlEzR9ytSa0+vS8Kw5xkFTTwf/ogY5mU3PIFIVTnINRkldVDi8fjE6FJuo5OYrccfM1phFxAalSeL3MjHSQK44wYPDs")
HashSet<object> h = new HashSet<object>();
foreach (object d in t)
{
DoSomething()
}
System.Web.UI.EventValidationStore is the object type (?)
I have tried to use a hash set, a list, etc. I am new to this, and it is was out of what I know how do do, but would love to learn it.
The error I get is: "foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public definition for 'GetEnumerator'"
I could not find anything on MSDN about the System.Web.UI.EventValidationStore.
I apologize if this is a confusing post, I am just not sure how to ask it.
Update: I successfully deserialized one EventValidation base64 string, but others are proving to be elusive. The one in the code segment does not seem to work.
Summary:
I need to be able to decode/deserialize and encode/serialize the eventvalidation base64 string in .NET.

The __EVENTVALIDATION field structure is internal to ASP.NET and is subject to change. Trying to deserialize / serialize it is unsupported. The supported ways of interacting with it are via the Page's ValidateEvent and RegisterForEventValidation APIs.
What exactly are you trying to accomplish? Perhaps we can find a supported way of doing it.

Related

Is it possible to deserialize json string into dynamic object using System.Text.Json?

I am using System.Text.Json package to use the serialization and deserialization.
I can deserialize a json string into an object when the type is explicitly specified like below.
var data = JsonSerializer.Deserialize<PersonType>(jsonString);
But the dynamic type does not work. Is it possible to deserialize without having to specify the type? Thank you!
var data = JsonSerializer.Deserialize<dynamic>(jsonString);
tl:dr JsonNode is the recommended way but dynamic typing with deserializing to ExpandoObject works and I am not sure why.
It is not possible to deserialize to dynamic in the way you want to. JsonSerializer.Deserialize<T>() casts the result of parsing to T. Casting something to dynamic is similar to casting to object
Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time
docs.
The following code snippet shows this happening with your example.
var jsonString = "{\"foo\": \"bar\"}";
dynamic data = JsonSerializer.Deserialize<dynamic>(jsonString);
Console.WriteLine(data.GetType());
Outputs: System.Text.Json.JsonElement
The recommended approach is to use the new JsonNode which has easy methods for getting values. It works like this:
JsonNode data2 = JsonSerializer.Deserialize<JsonNode>(jsonString);
Console.WriteLine(data2["foo"].GetValue<string>());
And finally trying out this worked for me and gives you want you want but I am struggling to find documentation on why it works because according to this issue it should not be supported but this works for me. My System.Text.Json package is version 4.7.2
dynamic data = JsonSerializer.Deserialize<ExpandoObject>(jsonString);
Console.WriteLine(data.GetType());
Console.WriteLine(data.foo);
I have tried using System.Text.Json in a dynamic way and it just does not work in an easy and meaningful way it seems. So while not a direct answer to your question, but I was "forced" to use the good old Newtonsoft.Json that just works:
dynamic result = JObject.Parse(message);

C# Dynamic List Class

I have a bit of a weird issue. Working in C# script with SSIS I have developed a need to build a List based off Dynamic Data.
Background
To explain it, a script task is fired that has a variable API URL, this goes off and pulls a JSON string back and then throws it into a strongly typed list using the following code.
var listobject = get_APIData<ApplicationOneDataSet>(url)
The class that does this is long winded and not really needed in the context of this issue.
ApplicationOneDataSet is a strongly typed match to one of the possible JSON results returned by get_APIData.
Now I have a need to change ApplicationOneDataSet to ApplicationTwoDataSet dynamically based on which API URL I pass to the script.
So what I have done is send through a second variable to the script called class name which contains the string "ApplicationDataSetOne" or "ApplicationDataSetTwo" based on which context I call it under.
The Question
My question is how can I dynamically vary this line:
var listobject = get_APIData<ApplicationOneDataSet>(url)
With the string variable passed into the script.
My original thinking was something along the lines of this:
var ClassType = (string) Dts.Variables["AppClassName"].Value;
Type type = Type.GetType(ClassType);
var listobject = get_APIData<type>(url)
Though it doesn't seem to like that. Any tips would be great!
As long as there is exactly two types you can use and you know them at compile time, I would not look further than a simple if. It works, it's easy, everyone understands it.
You can do it totally dynamic at runtime, but that's a huge pain in the... where you don't want it to be. If you really want to go down that rabbit hole, you can find more information here.
I'm not sure I fully understood what you are trying to do, but how about writing an interface ApplicationDataSet and then making a list of it? This way your list is going to be able to contain both types of data.

Json with a strange name field cannot be parsed

I have this JSON container that has a strange field called "48x48" for a photoUrl.
using Newtonsoft.Json;
(...)
dynamic issuesJson = JsonConvert.DeserializeObject(responseIssues.Content);
foreach (dynamic issue in issuesJson.issues){
Console.WriteLine(issue.name); //works properly
Console.WriteLine(issue.48x48); //error -> expected;
}
For some reason Visual Studio doesn't accept the access to this runtime field of this dynamic object. How can I work around this problem?
Note: I cannot change the field name.
Thanks anyway.
For some reason Visual Studio doesn't accept the access to this runtime field of this dynamic object.
Well what you've provided is simply not valid C#. An identifier can't start with a digit. That's still enforced even when you're trying to resolve a member of dynamic.
We don't know what type you're using for issues, but basically you'll need to handle it as a key/value map which you can access by string. Quite how you do that will depend on the implementation of issue. It doesn't look like Json.NET guarantees anything there - you may be able to cast it to JObject, for example:
foreach (JObject issue in issuesJson.issues) {
Console.WriteLine(issue["48x48"]);
}
Field names cannot start with a number. Sorry, no way around it.
You'll have to consult the documentation of your deserializer to see how it takes care of cases like that. It may be as simple as renaming the field "_48x48".
EDIT: actually, based on your code, you probably don't have a class representing this JSON object; I'm leaving my answer anyway, in case it helps someone else.
As others have mentioned, a C# identifier can't start with a digit. You just need to rename 48x48 to a valid name in your class, and map it to the actual JSON name using the [JsonProperty] attribute:
[JsonProperty("48x48")]
public string _48x48 { get; set; }

Deserializing JSON object to runtime type in WinRT (C#)

I have a small WinRT client app to my online service (Azure Web Service). The server sends a JSON encoded object with (with potential additional metadata) to the client and the client's responsibility would be to deserialize this data properly into classes and forward it to appropriate handlers.
Currently, the objects received can be deserialized with a simple
TodoItem todo = JsonConvert.DeserializeObject<TodoItem>(message.Content);
However, there can be multiple types of items received. So what I am currently thinking is this:
I include the type info in the header serverside, such as "Content-Object: TodoItem"
I define attributes to TodoItem on the client side (see below)
Upon receiving a message from the server, I find the class using the attribute I defined.
I call the deserialization method with the resolved type
(Example of the attribute mentioned in 2.)
[BackendObjectType="TodoItem"]
public class TodoItem
My problem with this approach however is the Type to Generics in the deserialization as I can't call:
Type t = ResolveType(message);
JsonConvert.DeserializeObject<t>(message.Content);
I tried finding some solutions to this and getting method info for the DeserializeObject and calling it using reflection seemed to be the way to go. However, GetMethod() does not exist in WinRT and I was not able to find an alternative I could use to retrieve the generic version of the DeserializeObject (as fetching by the name gives me the non-generic overload). I don't mind using reflection and GetMethod as I can cache (?) the methods and call them every time a message is received without having to resolve it every time.
So how do I achieve the latter part and/or is there another way to approach this?
Alright, I feel like this was not really a problem at all to begin with as I discovered the DeserializeObject(string, Type, JsonSerializerSettings) overload for the method. It works splendidly. However, I would still like to hear some feedback on the approach. Do you think using attributes as a way to resolve the type names is reasonable or are there better ways? I don't want to use the class names directly though, because I don't want to risk any sort of man-in-the-middle things be able to initialize whatever.
Just a few minutes ago we have posted the alternative way to do what you want. Please look here, if you will have any questions feel free to ask:
Prblem in Deserialization of JSON
Try this
http://json2csharp.com/
Put your Json string here it will generate a class
then
public static T DeserializeFromJson<T>(string json)
{
T deserializedProduct = JsonConvert.DeserializeObject<T>(json);
return deserializedProduct;
}
var container = DeserializeFromJson<ClassName>(JsonString);

From object to proper types: Is this the/a "right" way to work with this non-generified, object-returning API?

One particular aspect of some code I've written is causing me minor headaches, I can't pinpoint the reason - all the type checking and casting is making me feel uneasy. The code works as it is right now. I'd like to know wether or not there's a better way to handle the type-specific aspects of the code.
I'm using a non-generified, object-returning JSON parser which makes me go through various incantations in my generified code.
The signature of the parse method is public static object JsonDecode(string json) The runtime type of the object it returns can be ArrayList, Hashtable, double or string. I'm calling the JsonDecode method on a Twitter Search response, which returns the result tweets as a top level object of the form:
{"results":[
{"text":"#twitterapi http:\/\/tinyurl.com\/ctrefg",
"to_user_id":396524,
"to_user":"TwitterAPI",
"from_user":"jkoum",
"metadata":
{
"result_type":"popular",
"recent_retweets": 109
}, ... MORE-DATA ...}
The context in which I'm using the JsonDecode(string json) method is
private IList<Tweet> searchResult = new List<Tweet>();
var jsonDecoded = JSON.JsonDecode(responseString);
IList rawTweets =
(IList)((Hashtable)jsonDecoded)["results"];
foreach (var rawTweet in rawTweets)
{
searchResult.Add(new Tweet((Hashtable) rawTweet));
}
The Tweet class does its own type checking and casting
class Tweet : DynamicObject
{
private IDictionary<string, string> stringValues =
new Dictionary<string, string>();
private IDictionary<string, double> numberValues =
new Dictionary<string, double>();
public Tweet(Hashtable rawTweet)
{
FlattenJSON(rawTweet);
}
//flatten input and assign to correct map/dictionary based on JSON value type
private void FlattenJSON(Hashtable table)
{
foreach (DictionaryEntry entry in table)
{
//this code is not handling the case, that the Tweet contains a JSON array
//not necessary as of now: this code is intended for demo purposes in a talk
//I'm giving on Friday 2010-06-25
if (entry.Value is String)
stringValues.Add((string)entry.Key, (string)entry.Value);
else if (entry.Value is Double)
numberValues.Add((string)entry.Key, (double)entry.Value);
else if (entry.Value is Hashtable)
FlattenJSON((Hashtable)entry.Value);
}
}
...
}
Am I handling the type checks in the FlattenJSON method correctly? What about the casts in the code snippet building the IList and constructing the searchResult IList<Tweet>? Would you have written the code in a different way?
As a side note, the complete code is available via http://github.com/codesurgeon/pop-tweets The code is intended for a demo in a talk that I'll be giving on selected .NET features. The Tweet class is a DynamicObject and it overrides TryGetMember, see full listing on github.
Thank you ;)
P.S.: [FYI] This is a more specific version of my previous post, requesting a general code review https://stackoverflow.com/questions/3113293/how-to-be-a-good-c-citizen-review-requested-for-c-4-0-dynamic-sample-code
A few things stand out to me:
First, you should so some argument validation. Check to see if "table" is null before you start using it. Otherwise, you will get an unhandled NullReferenceException and it will confuse your consumer.
Next, does this actually work? The "is" keyword (I thought) only worked with reference types, and double is a value type. I would assume that this wouldn't work and you'd need to instead do a double.TryParse().
Lastly, there is a lot of casting on-the-fly. When you are interacting with a 3rd-party API, I would argue that you should have an interface where you convert from "their weird stuff" to "your clean stuff". So even if the API is messy and difficult, clean it up and present it to your consumer in the proper way. Don't propogate the bad design. In other words, as a consuming developer, I would want some obvious and clean data structures to work with. Like: foreach(Tweet tweet in Twitter.GetTweets()) or something. I don't care that you happen to use json right now. That implementation should be be invisible to me.
Hope that helps...
I would not do it like that.
First of all, your tweet class is not a real object, it's a data container. You could just continue to work with the jsonDecoded variable, since your tweet class doesn't add any functionality or abstraction (other than abstracting away the JSON decoder).
How I would do it:
Create POCOs which holds the information: Tweet and a Metadata class.
Create a serializer which takes the JSON string and returns the Tweet class
By dividing it into two steps and also creating real classes you will have it much easier in the future. Please read about Single Responsibility.

Categories