问题
We have a .NET client, which use SignalR to call Server method, but the parameter seems very big, for such scenario how to fix it?
Client code:
public async Task FooAsync()
{
var hubConnection = new HubConnection(...);
await hubConnection.Start();
var hubProxy = hubConnection.CreateHubProcx("ValueHub");
//the content is very long, about 11776065 bytes (11MB)
var content = File.ReadAllText(...);
hubProxy.Invoke("Send", content);
...
}
Server code:
[HubName("ValueHub")]
public class ValueHub : Hub
{
public void Send(string json)
{
}
}
From the exception stack and source code, I found the SignalR internally use HttpClient
with the FormUrlEncodedContent
type HttpContent
, and maybe the limitation came from here.
System.UriFormatException was unhandled
HResult=-2146233033
Message=Invalid URI: The Uri string is too long.
Source=System
StackTrace:
at System.UriHelper.EscapeString(String input, Int32 start, Int32 end, Char[] dest, Int32& destPos, Boolean isUriString, Char force1, Char force2, Char rsvd)
at System.Uri.EscapeDataString(String stringToEscape)
at System.Net.Http.FormUrlEncodedContent.Encode(String data)
at System.Net.Http.FormUrlEncodedContent.GetContentByteArray(IEnumerable`1 nameValueCollection)
at System.Net.Http.FormUrlEncodedContent..ctor(IEnumerable`1 nameValueCollection)
at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.Post(String url, Action`1 prepareRequest, IDictionary`2 postData, Boolean isLongRunning)
at Microsoft.AspNet.SignalR.Client.Transports.HttpBasedTransport.Send(IConnection connection, String data, String connectionData)
at Microsoft.AspNet.SignalR.Client.Transports.AutoTransport.Send(IConnection connection, String data, String connectionData)
at Microsoft.AspNet.SignalR.Client.Connection.Send(String data)
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke[T](String method, Object[] args)
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke(String method, Object[] args)
Any good suggestions over this problem?
回答1:
As you have already gathered - this data is too much for SIGNALR by it's own design.
Would it not be a better idea to rather have another process that does this with a normal REST API (GET/POST). Perhaps a message indicating to the user that this needs to be done, as this feels very 'BATCH' like.
Secondly, if it a requirement (possible wrong tool for the job), have you considered compression.
回答2:
You can add a line that makes the message size 'infinite 'in your Startup.cs by setting the MaxIncomingWebSocketMessageSize to null:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null;
}
}
}
Mine works with ~200kb of data, 10 messages send consistently. I don't know how well it works if there is more data send per second though.
回答3:
its easy to do it..
- split files into byte Array chunks (my tests shows max 10kb per chunk is enough)
send chunks to client with an invoke like (calculate
totalBytes
and the chunk data you have) :hubProxy.Invoke("Send", chunk,currentBytes,totalBytes);
- get the chunks from client and create a byte array and append each chunk, signalr sends files syncronously, this means data will be received as your send order
- you have
totalbytes
andcurrentBytes
data, now you know all data received, save this byte array to a file with stream or whatever you like..
回答4:
add this to web config<httpRuntime maxRequestLength="1048576" executionTimeout="600" />
then add this code to Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null;
}
}
来源:https://stackoverflow.com/questions/24262041/how-to-send-big-data-via-signalr-in-net-client