Serialization "Exception has been thrown by the target of an invocation." - c#

Few days ago I've asked a question about object serialization and the answer was working well, actually it still works. But somehow I've copied the serialize function to an another class but didn't fit here and I have no idea why.
Exception has been thrown by the target of an invocation.
Inner Exception: An invalid argument was supplied.
Client.cs
public class Client
{
private string username;
public string Username
{
get { return username; }
set { username = value; }
}
private TcpClient tclient;
public TcpClient tClient
{
get { return tclient; }
set { tclient = value; }
}
public Client()
{}
public string Serialize(object obj)
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public object Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize<object>(json);
}
}
Any ideas?

Since the TcpClient class is not a serializable class you can't simply serialize it. But as you can see here it has a constructor with (string: server, int: port) so you can add these fields to your class then after deserialization you can create it again.
Ps: It's funny that I was the one answered your previous question, here we are again.

Related

Generic function [duplicate]

This question already has answers here:
How to get a property value using reflection
(2 answers)
Closed 8 years ago.
I'm trying to create a simple generic function:
public T GetPost<T>(HttpListenerRequest request) where T : new()
{
Stream body = request.InputStream;
Encoding encoding = request.ContentEncoding;
StreamReader reader = new StreamReader(body, encoding);
string data = reader.ReadToEnd();
body.Close();
reader.Close();
// NullRefferenceException on this line:
typeof(T).GetField("Name").SetValue(null, "djasldj");
return //yet to come
}
Strangely the line with typeof(T) return this error:
Object reference not set to an instance of an object.
What is a NullReferenceException, and how do I fix it?
Also how can I return the constructed T class?
This is how I call the function:
string data = GetPost<User>(ctx.Request);
And this is the User class:
public static string Name { get; set; }
public string Password { get; set; }
The problem with your code is that you look for a field, but your T has an automatic property.
You thus need to call:
typeof(T).GetProperty("Name").SetValue(null, "djasldj");
This code for instance (stripped unnecessary code) works:
class Foo {
public static string Name { get; set; }
public string Password { get; set; }
}
class Program
{
static void Main()
{
Console.WriteLine(Foo.Name);
GetPost<Foo>();
Console.WriteLine(Foo.Name);
}
public static void GetPost<T>() where T : new() {
typeof(T).GetProperty("Name").SetValue(null, "djasldj");
}
}
I'm afraid you're trying to set property of T. But T is only a type you pass to the generic method. You've constrained it with new(), so as far as I know T type should provide parameterless constructor.
Let's say you call it GetPost<User>(request);
It should return user with some properties set. Take a look on that example (User class is as you wrote)...
This is a class with generic method:
namespace ConsoleApplication1
{
class Class1
{
public T GetPost<T>(string s) where T : new()
{
if (typeof(T)== typeof(User))
{
var result = new User();
result.Password = "some";
return (T)(object)result;
}
else
{
throw new ArgumentException();
}
}
}
}
And this is usage
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var c = new Class1();
var obj = c.GetPost<User>("dsjkd");
}
}
}
After execution variable "obj" is User object with password field set.
EDIT:
I've just seen CommuSoft post. It's better solution I think, but I'm not deleting my answer, maybe someone will find it useful.

Deserialize json into C# object for class which has default private constructor

I need to deserialize json for following class.
public class Test
{
public string Property { get; set; }
private Test()
{
//NOTHING TO INITIALIZE
}
public Test(string prop)
{
Property = prop;
}
}
I can create an instance of Test like
var instance = new Test("Instance");
considering my json something like
"{ "Property":"Instance" }"
How shall I create an object of Test class as my default constructor is private and I am getting object where Property is NULL
I am using Newtonsoft Json parser.
You can make Json.Net call the private constructor by marking it with a [JsonConstructor] attribute:
[JsonConstructor]
private Test()
{
//NOTHING TO INITIALIZE
}
Note that the serializer will still use the public setters to populate the object after calling the constructor.
Another possible option is to use the ConstructorHandling setting:
JsonSerializerSettings settings = new JsonSerializerSettings
{
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
Test t = JsonConvert.DeserializeObject<Test>(json, settings);
It doesn't seem like you need to take any extra steps.
Using Json.NET v6.0.8, the following C# program works inside LINQPad:
void Main()
{
var o = JsonConvert.DeserializeObject<Test>("{\"Property\":\"Instance\"}");
Debug.Assert(o.Property == "Instance",
"Property value not set when deserializing.");
}
public class Test
{
public string Property { get; set; }
private Test()
{
}
public Test(string propertyValue)
{
Property = propertyValue;
}
}
No need to create a Serializer setting and give assign ConstructorHandling here. Please remember to define the [JsonConstructor] attribute to the private constructor.
I have similar case with abstract BaseNode.cs and its concrete ComputerNode.cs implementation. You can create the classes, copy/paste the code below and do some experiment.
public abstract class BaseNode
{
[JsonConstructor] // ctor used when Json Deserializing
protected BaseNode(string Owner, string Name, string Identifier)
{
this.Name = Name;
this.Identifier = Identifier;
}
// ctor called by concrete class.
protected BaseNode(string [] specifications)
{
if (specifications == null)
{
throw new ArgumentNullException();
}
if (specifications.Length == 0)
{
throw new ArgumentException();
}
Name = specifications[0];
Identifier = specifications[1];
}
public string Name{ get; protected set; }
public string Identifier { get; protected set; }
}
public class ComputerNode: BaseNode
{
public string Owner { get; private set; }
[JsonConstructor] // not visible while creating object from outside and only used during Json Deserialization.
private ComputerNode(string Owner, string Name, string Identifier):base(Owner, Name, Identifier)
{
this.Owner = Owner;
}
public ComputerNode(string[] specifications):base(specifications)
{
Owner = specifications[2];
}
}
For JSon Read and Write following code helps -
public class Operation<T>
{
public string path;
public Operation()
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "nodes.txt");
if (File.Exists(path) == false)
{
using (File.Create(path))
{
}
}
this.path = path;
}
public void Write(string path, List<T> nodes)
{
var ser = JsonConvert.SerializeObject(nodes, Formatting.Indented);
File.WriteAllText(path, ser);
}
public List<T> Read(string path)
{
var text = File.ReadAllText(path);
var res = JsonConvert.DeserializeObject<List<T>>(text);
return res;
}
}
All the best!
Today the short answer is: Rename the constructor parameter prop to property and your code will work fine.
public class Test
{
public string Property { get; }
public Test(string property)
{
Property = property;
}
}
Console.WriteLine(
JsonConvert.DeserializeObject(new Test("Instance")));
Newtonsoft.Json supports initializing properties using constructor parameters out of the box, without needing to set any additional attributes or changing any settings. The only constraint is that the parameter name needs to be a case insensitive match to the property name.
I discovered today that having a public constructor that takes parameters and no declared unparameterized constructor causes NewtonSoft to attempt to call the public constructor, the only one that it can find, since there is no explicit default constructor, and it cannot apparently find and call the default constructor provided by the framework unless it is the only constructor.
Explicitly declaring a default constructor causes NewtonSoft to call the correct (unparameterized) constructor.

Custom Xml Serialization breaks list functionality

Ok, so I've got a type:
public class MonitorConfiguration
{
private string m_sourcePath;
private string m_targetPath;
public string TargetPath
{
get { return m_targetPath; }
set { m_targetPath = value; }
}
public string SourcePath
{
get { return m_sourcePath; }
set { m_sourcePath = value; }
}
//need a parameterless constructor, just for serialization
private MonitorConfiguration()
{
}
public MonitorConfiguration(string source, string target)
{
m_sourcePath = source;
m_targetPath = target;
}
}
When I serialise and deserialise a list of these, like this
XmlSerializer xs = new XmlSerializer(typeof(List<MonitorConfiguration>));
using (Stream isfStreamOut = isf.OpenFile("Test1.xml", FileMode.Create))
{
xs.Serialize(isfStreamOut, monitoringPaths);
}
using (Stream isfStreamIn = isf.OpenFile("Test1.xml", FileMode.Open))
{
monitoringPaths = xs.Deserialize(isfStreamIn) as List<MonitorConfiguration>;
}
everything works fine.
However, I really want to hide the public setters of the attributes. This prevents them from being serialised by the XML serialiser. So, I implement my own, like this:
Change the class declaration to this:public class MonitorConfiguration : IXmlSerializable
and add these:
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
//make sure we read everything
while (reader.Read())
{
//find the first element we care about...
if (reader.Name == "SourcePath")
{
m_sourcePath = reader.ReadElementString("SourcePath");
m_targetPath = reader.ReadElementString("TargetPath");
// return;
}
}
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteElementString("SourcePath", m_sourcePath);
writer.WriteElementString("TargetPath", m_targetPath);
}
This seems to work, however, I only ever get the first item from the list out, all the others are forgotten. I've tried with and without the return that's currently commented out. What am I doing wrong here?
It should be noted that this is just a snippet code that illustrates the problem; I'm limited to which XML serialisation technology I'm using my an eternal mechanic.
This CodeProject article explains how to get around a few pitfalls when working with IXmlSerializable.
Specifically, you probably need to call reader.ReadEndElement(); when you've found all your elements in ReadXml (see the section How to Implement ReadXml? in the article).

Web API silently fails for data types without a default parameterless constructor

I have a similar problem to this SO question: Deserializing JSON to object with no default constructor in ASP.NET MVC 3 but in MVC4 and the quoted solution didn't work for me.
Essentially, If I have a class like;
public class MyObject
{
public string name = "foo";
public int age = 33;
public MyObject(string n)
{
name = n;
}
}
and I try to return it from a Web API method;
// GET api/values/5
public **MyObject** Get(int id)
{
return new MyObject("Getted");
}
The plumbing just throws my request on the floor. It silently fails with a 500 error. Now I might expect it to struggle, but I'd prefer an exception. It's not clear where this is being generated but I've tried intercepting at a number of points (FilterProvider, ValueProvider, ModelBinder) and I can't see to see which part of the plumbing is throwing it out.
This custom model binder does not even get called for instance;
public class MyObjectModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
return new MyObject("bound model");
}
}
For completeness, this was registered in global.asax.cs;
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// other stuff...
ModelBinders.Binders.Add(typeof(MyObject), new MyObjectModelBinder());
}
}
Curiously, if I add a default constructor, it's never actually called, but the Web API plumbing just won't seem to work without it.
This does work (strangely);
public class MyObject
{
public string name = "foo";
public int age = 33;
public MyObject()
{
throw new Exception("I am never called! But I must exist");
}
public MyObject(string n)
{
name = n;
}
}
I was considering raising an issue on connect.microsoft.com regarding the silent failure, but presumably there must be a workaround.
Can anyone shed any light on what I'm doing wrong?
I was trying repro your issue with the following code, but it works fine. Can you try to attach a repro?
class Program
{
private const string baseAddress = "http://localhost:8080/";
static void Main(string[] args)
{
HttpSelfHostConfiguration configuration = new HttpSelfHostConfiguration(baseAddress);
configuration.Routes.MapHttpRoute("default", "api/{controller}");
HttpSelfHostServer server = new HttpSelfHostServer(configuration);
try
{
server.OpenAsync().Wait();
RunClient();
}
finally
{
server.CloseAsync().Wait();
}
}
static void RunClient()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(baseAddress);
HttpResponseMessage response = client.GetAsync("api/Test?id=1").Result;
response.EnsureSuccessStatusCode();
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
}
public class MyObject
{
public string name = "foo";
public int age = 33;
public MyObject(string n)
{
name = n;
}
}
public class TestController : ApiController
{
// GET api/values/5
public MyObject Get(int id)
{
return new MyObject("Getted");
}
}
Can you please attach a repro for this?
BTW, there is a tracing package you can use to find out more information what went wrong.
http://www.nuget.org/packages/Microsoft.AspNet.WebApi.Tracing/0.3.0-rc
You can learn more about how to use this from http://blogs.msdn.com/b/roncain/archive/2012/08/16/asp-net-web-api-tracing-preview.aspx
Thanks!
best,
hongmei

Generics + XML Serialization + Custom Objects

I'm trying out Generics and I had this (not so) great idea of creating an XMLSerializer class. The code I pieced together is below:
public class Persist<T>
{
private string _path;
public Persist(string path) {
this._path = path;
}
public void save(T objectToSave)
{
XmlSerializer s = new XmlSerializer(typeof(T));
TextWriter w = new StreamWriter(this._path);
try { s.Serialize(w, objectToSave); }
catch (InvalidDataException e) { throw e; }
w.Close(); w.Dispose();
}
public T load()
{
XmlSerializer s = new XmlSerializer(typeof(T));
TextReader r = new StreamReader(this._path);
T obj;
try { obj = (T)s.Deserialize(r); }
catch (InvalidDataException e) { throw e; }
r.Close(); r.Dispose();
return obj;
}
}
Here's the problem: It works fine on Persist<List<string>> or Persist<List<int>> but not on Persist<List<userObject>> or any other custom (but serializable) objects. userObject itself is just a class with two {get;set;} properties, which I have serialized before.
I'm not sure if the problems on my Persist class (generics), XML Serialization code, or somewhere else :( Help is very much appreciated~
Edit:
code for userObject
public class userObject
{
public userObject(string id, string name)
{
this.id = id;
this.name = name;
}
public string id { get;private set; }
public string name { get;set; }
}
Looks to me like your code should just work - even though it does have a few flaws.
EDIT: Your userObject class isn't serializable. Xml serialization only works on types with a public, parameterless constructor - the current class won't work. Also, you should really rewrite your code to avoid explicit calls to .Close() or .Dispose() and instead prefer using where possible - as is, you might get random file locking if at any point during serialization an error occurs and your method terminates by exception - and thus doesn't call .Dispose().
Personally, I tend to use a just-for-serialization object hierarchy that's just a container for data stored in xml and avoids any behavior - particularly side effects. Then you can use a handly little base class that makes this simple.
What I use in my projects is the following:
public class XmlSerializableBase<T> where T : XmlSerializableBase<T>
{
static XmlSerializer serializer = new XmlSerializer(typeof(T));
public static T Deserialize(XmlReader from) { return (T)serializer.Deserialize(from); }
public void SerializeTo(Stream s) { serializer.Serialize(s, this); }
public void SerializeTo(TextWriter w) { serializer.Serialize(w, this); }
public void SerializeTo(XmlWriter xw) { serializer.Serialize(xw, this); }
}
...which caches the serializer in a static object, and simplifies usage (no generic type-paramenters needed at call-locations.
Real-life classes using it:
public class ArtistTopTracks {
public string name;
public string mbid;//always empty
public long reach;
public string url;
}
[XmlRoot("mostknowntracks")]
public class ApiArtistTopTracks : XmlSerializableBase<ApiArtistTopTracks> {
[XmlAttribute]
public string artist;
[XmlElement("track")]
public ArtistTopTracks[] track;
}
Sample serialization calls:
using (var xmlReader = XmlReader.Create([...]))
return ApiArtistTopTracks.Deserialize(xmlReader);
//[...]
ApiArtistTopTracks toptracks = [...];
toptracks.SerializeTo(Console.Out);
There can be a number of reasons why your code fails: This text is particularly helpful when having issues: Troubleshooting Common Problems with the XmlSerializer . Maybe you have some type hierarchy in your user objects and the serializer does not know about it?

Categories

Resources