LueTm
LueTm

Reputation: 2380

SignalR hangs on foreign keys

I have a SignalR server that should transmit Message objects from the server to the client. The hub-method looks like this:

public IEnumerable<Message> GetMessages()
{
    try
    {
        using (var context = new PsmContext())
        {
            context.Configuration.LazyLoadingEnabled = false;
            context.Configuration.ProxyCreationEnabled = false;

            return context.Messages
                .Include("Machine")
                .ToList();
        }
    }
    catch (Exception err)
    {
        Logging.Log(Logging.ServerLog, err);
        return new List<Message>();
    }
}

The data is organized in the following way: A Message originates from a Machine, and a Machine is on a Site. A Site in turn has multiple Machines. This important: Machine has no navigation property for the type Message, but Machine and Site reference each other:

// Machine.cs
public virtual Site Site { get; set; }
public int SiteId { get; set; }

// Site.cs
public virtual ICollection<Machine> Machines { get; set; }

When I query the data like I showed above, everything works. But as soon as I add

.Include("Machine.Site")

the client never gets his anwser (await HubProxy.Invoke<IEnumerable<Message>>("GetMessages") hangs forever). The funny thing is, that the hub-method returns - I tested that with log entries. This means, that the failure is somewhere in the internals of SignalR.

I assume, this is because of the Machine and Site entities referencing each other, causing the serialization of the objects to fail. How can I fix that?

(The client is a .NET 4.5 client, if that matters, the hub runs in IIS 8.5)

Upvotes: 3

Views: 310

Answers (1)

Admir Tuzović
Admir Tuzović

Reputation: 11177

If you believe serialization is an issue, Newtonsoft.Json has 3 values for reference loop handling:

public enum ReferenceLoopHandling
    {
        // Summary:
        //     Throw a Newtonsoft.Json.JsonSerializationException when a loop is encountered.
        Error = 0,
        //
        // Summary:
        //     Ignore loop references and do not serialize.
        Ignore = 1,
        //
        // Summary:
        //     Serialize loop references.
        Serialize = 2,
    }

So you can change it and testing in Global.Asax / Startup.cs:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Error
            };

I don't know if this will help you out, but at least you can test to see if serialization is really issue of your problem.

How will you handle the error if it really is up to your design, but I'd go with some view models instead of sending raw entity objects back to the client side.

Upvotes: 0

Related Questions