0

I have some problems invoking a signalr hub when the returned object is a Castle DynamicProxy.

Let's say that I have the following server code on the signalr hub (this is not the real code but just to show the problem):

public Article Read()
{
    var article = new Article(0);
    return article;
}
public class Article
{
    public Article(int id)
    {
        Id = id;
    }

    public int Id { get; set; }
}

The above method correctly returns my object. If I change this code to:

public Article Read()
{
    var proxyGenerator = new Castle.DynamicProxy.ProxyGenerator();
    var entity = proxyGenerator.CreateClassProxy(typeof(Article), new object[]{0}, new TestInterceptor()) as Article; ;
    return entity;
}
class TestInterceptor : Castle.DynamicProxy.IInterceptor
{
    public void Intercept(Castle.DynamicProxy.IInvocation invocation)
    {
    }
}

The object is never returned. The client (javascript) doesn't receive any error and neither done or fail function are executed.

I suspect it is a problem with the serialization. If I try to serialize the object using Newtonsoft I get the following error:

System.ArgumentNullException was unhandled by user code
  HResult=-2147467261
  Message=Value cannot be null.
Parameter name: key
  Source=mscorlib
  ParamName=key
  StackTrace:
       at System.Collections.ObjectModel.KeyedCollection`2.Contains(TKey key)
       at Newtonsoft.Json.Serialization.JsonPropertyCollection.AddProperty(JsonProperty property)
       at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties)
       at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type objectType)
       at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType)
       at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type)
       at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.GetContractSafe(Object value)
       at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
       at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
       at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
       at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, Formatting formatting, JsonSerializerSettings settings)
       at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings)
       at Newtonsoft.Json.JsonConvert.SerializeObject(Object value)
  InnerException: 

Any ideas? It is a serialization problem of signalr?

EDIT:

Thanks to Anders I have found that the problem occurs only when the class for which you have created the dynamic proxy doesn't have a default constructor. For example public Article(int id). It is a problem with Json.NET serialization?

Davide Icardi
  • 11,919
  • 8
  • 56
  • 77
  • SignalR uses JSON.NET so if JSON.NET can't deserialize the object for some reason (the above exception) it won't work in SignalR either. – davidfowl Sep 22 '13 at 23:29
  • @dfowler Thanks David. The only strange think is that I don't receive any error from SignalR. Eventually it is possible to use a custom serialization? Or directly return a json? – Davide Icardi Sep 23 '13 at 15:07
  • We don't give nice errors here because we write the response in chunks . We're going to look into reporting this error is a better way in the future. You can certainly serialize yourself and send strings (though you'd be double serializing). JSON.NET also has serializer pluggability – davidfowl Sep 23 '13 at 17:53

2 Answers2

1

Json.Net has no problem serialize a Dynamic proxy, this worked for me

class Program
{
    static void Main(string[] args)
    {
        var proxyGenerator = new Castle.DynamicProxy.ProxyGenerator();
        var entity = proxyGenerator.CreateClassProxy(typeof(Article), new object[0], new TestInterceptor()) as Article; ;
        var json = JsonConvert.SerializeObject(entity);
    }
}

public class Article
{
    public int Id { get; set; }
}

class TestInterceptor : Castle.DynamicProxy.IInterceptor
{
    public void Intercept(Castle.DynamicProxy.IInvocation invocation)
    {
    }
}   

Result was

{"__interceptors":[{}],"Id":0}

update:

Without parameterless constructor I get an expection allready in Castle

Can not instantiate proxy of class: ConsoleApplication1.Article.

Could not find a parameterless constructor.
Anders
  • 17,306
  • 10
  • 76
  • 144
  • Sorry Anders you are right. In fact my production code is slightly different. Seems to be a problem when using Dynamic Proxy when the class doesn't have a default constructor. Basically if Article class has only a constructor with parameters, like `public Article(int id)` the exception ArgumentNullException is throw. Do you think it is a bug with Json.NET? Consider that if I serialize the same class without DynamicProxy it works fine. – Davide Icardi Sep 23 '13 at 13:23
  • You must pass the constructor arguments to the proxy generator: `proxyGenerator.CreateClassProxy(typeof(Article), new object[]{param1}, new TestInterceptor()) as Article;` In this way Castle correctly generate the proxy but Json.NET throw an exception on the serialization. – Davide Icardi Sep 23 '13 at 14:46
  • After some more investigation I have found the problem. It is a little bug on Json.NET. I have created a [new issue](http://json.codeplex.com/workitem/24724) on json.net website that now has been resolved. – Davide Icardi Oct 03 '13 at 15:19
1

After some more investigation I have found the problem. It is a little bug on Json.NET. I have created a new issue on json.net website that now has been resolved.

Davide Icardi
  • 11,919
  • 8
  • 56
  • 77