2014-06-17 58 views
7

Abbiamo un client .NET, che usa SignalR per chiamare il metodo Server, ma il parametro sembra molto grande, per tale scenario come risolverlo?Come inviare grandi dati tramite SignalR in client .NET

Codice cliente: Codice

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:

[HubName("ValueHub")] 
public class ValueHub : Hub 
{ 
    public void Send(string json) 
    { 

    } 
} 

dallo stack eccezione e il codice sorgente, ho trovato il SignalR utilizzare internamente HttpClient con il FormUrlEncodedContent tipo HttpContent, e forse la limitazione è venuto da qui.

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) 

Qualche suggerimento su questo problema?

+4

Onestamente non lo farei in un hub. Utilizzare l'hub come framework di messaggistica per informare il cliente che sono arrivati ​​nuovi dati. Il cliente può quindi recuperare i dati tramite web api/webmethod o qualsiasi altra tecnica di trasporto. – Schadensbegrenzer

+0

Questo potrebbe aiutarti http://stackoverflow.com/questions/7043566/invalid-uri-the-uri-string-is-toollong –

+0

Qual è il caso d'uso? – Anders

risposta

6

Come già visto, questo dato è troppo per SIGNALR per il suo design.

Non sarebbe una buona idea preferire un altro processo che faccia ciò con una normale API REST (GET/POST). Forse un messaggio che indica all'utente che questo deve essere fatto, in quanto questo sembra molto "BATCH".

In secondo luogo, se si tratta di un requisito (possibile strumento errato per il lavoro), è stata considerata la compressione.

+0

E i file più piccoli? Voglio inviare miniature da 60KB. Posso dire al mio server di accettare una stringa di query così lunga (e sarà comunque abbastanza veloce), ma la codifica uri di SignalR lo bloccherà ancora: S. –

1

la sua facile da farlo ..

  • file divisi in blocchi di byte array (10kb max miei test mostra per ogni pezzo è sufficiente)
  • inviare blocchi di client con un invoke come (calcolare totalBytes e i dati pezzo si dispone):

    hubProxy.Invoke("Send", chunk,currentBytes,totalBytes); 
    
  • ottenere i pezzi dal client e creare un array di byte e aggiungere ogni pezzo, signalr invia i file syncronously, questo significa che i dati saranno ricevuti come send Per
  • avete totalbytes e currentBytes dati, ora sapete ricevuto tutti i dati, salvare questo array di byte in un file con flusso o quello che vuoi ..
+0

Avresti bisogno di inviare informazioni sulla sequenza insieme a esso mentre leggo che SignalR non garantisce l'ordine dei messaggi. – TheLegendaryCopyCoder

9

È possibile aggiungere una linea che rende la dimensione del messaggio ' infinita 'nelle vostre Startup.cs impostando il MaxIncomingWebSocketMessageSize a nulla:

public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
     app.MapSignalR(); 
     GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null; 
     } 
    } 
} 

miniera funziona con ~ 200kb dei dati, 10 messaggi invio in modo coerente. Non so come funziona se ci sono più dati inviati al secondo però.

+0

Funzionante alla grande. bella soluzione. – No1Lives4Ever

+0

Non ha vinto per me. Maggio perché è un'app owin con Web Api e Signalr e la configurazione deve essere impostata diversamente –

+0

Nel caso in cui SignalR si trovi all'interno di un'app Owin, la risposta sopra deve essere combinata con questo http://jerodkrone.com/signalr-2 -0-dependency-injection-using-globalhost/per funzionare. Quindi se l'hub utilizza una configurazione personalizzata come var hubconfig = new HubConfiguration(); e un resolver personalizzato come hubconfig.Resolver = new AutofacDependencyResolver (lifetimeScope); quindi è necessario aggiungere le seguenti 2 righe in StartUp: GlobalHost.DependencyResolver = hubconfig.Resolver; GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null; –

Problemi correlati