locked
Error posting 1.4KB string from Silverlight to WCF Data Service RRS feed

  • Question

  • I'm using SL 5 and WCF DS 5. I'm calling a service POST operation where a string is sent as input which is basically contents of a text file. It seems when the string is smaller, it works, but when it is around 1.4KB (size of the text file), this error is thrown:

        {System.InvalidOperationException: An error occurred while processing this request. ---> System.Exception: Error HRESULT E_FAIL has been returned from a call to a COM component.
       at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
       at System.Data.Services.Http.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
       at System.Data.Services.Client.HttpWebRequestMessage.EndGetResponse(IAsyncResult asyncResult)
       at System.Data.Services.Client.HttpTransportLayer.EndGetResponse(IODataRequestMessage requestMessage, IAsyncResult asyncResult)
       at System.Data.Services.Client.DataServiceContext.GetResponseHelper(ODataRequestMessageWrapper request, IAsyncResult asyncResult, Boolean handleWebException)
       at System.Data.Services.Client.QueryResult.AsyncEndGetResponse(IAsyncResult asyncResult)
       --- End of inner exception stack trace ---
       at System.Data.Services.Client.BaseAsyncResult.EndExecute[T](Object source, String method, IAsyncResult asyncResult)
       at System.Data.Services.Client.QueryResult.EndExecuteQuery[TElement](Object source, String method, IAsyncResult asyncResult)
       at System.Data.Services.Client.DataServiceRequest.EndExecute[TElement](Object source, DataServiceContext context, String method, IAsyncResult asyncResult)
       at System.Data.Services.Client.DataServiceContext.EndExecute[TElement](IAsyncResult asyncResult)

    I called the same operation from a WPF app, and it works fine. I also did this on the WCF DS host:

        WebHttpBinding binding = new WebHttpBinding();
                binding.MaxReceivedMessageSize = int.MaxValue;
                binding.MaxBufferPoolSize = int.MaxValue;
                binding.MaxBufferSize = int.MaxValue;
                binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;

    Here is the call from the SL client:

        CodeFirstContainer context;

                context = new CodeFirstContainer(new Uri("http://localhost:4444/MyDataService/"));

                OperationParameter p = new UriOperationParameter("fileIDN", fileIDN);
                OperationParameter p1 = new UriOperationParameter("fileContent", fileContent);

                context.BeginExecute<int>
                    (new Uri(context.BaseUri.OriginalString + "ProcessTextFile"),
                        (r) =>
                        {
                            Deployment.Current.Dispatcher.BeginInvoke(() =>
                            {
                                try
                                {
                                    context = r.AsyncState as CodeFirstContainer;

                                    // Get the response of the query.
                                    var response = context.EndExecute<int>(r).ToList();
                                }
                                catch (Exception ex)
                                {
                                }
                            }
                            );
                        },
                        context, "POST", true, new OperationParameter[] { p, p1 }
                    );

    Thanks,

    cp

                
    • Edited by cp.net Wednesday, November 28, 2012 10:43 PM
    Wednesday, November 28, 2012 10:42 PM

Answers

  • Service operations pass parameters in the URL. So your string will end up in a URL query option. Different HTTP components have different limits on the URL size, but in general these limits are pretty small (typically anything above cca 1000 characters will run into trouble). This can happen on the client (as you're seeing) or in between (proxies, caches, ...) or on the server (IIS has limits on this, WCF has others of its own and so on).

    So the general advice is - do not send large parameters to service operations.

    This can be "fixed" in two ways:

    1) Use Actions - WCF DS 5.0 (OData V3) introduces actions which behave very similarly to service operations, but they can take the parameters in the body of the request (as oppose to the URI).

    2) Model this part of the service as entity. So instead of sending a file as a parameter- create a new entity and send the file as its binary stream.

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by cp.net Friday, November 30, 2012 8:18 PM
    Thursday, November 29, 2012 4:39 PM
    Moderator
  • In this article there's a good description of what needs to be set in WCF to make it truly streaming: http://msdn.microsoft.com/en-us/library/ee960144.aspx

    I think your setup above will allow large data but it will still buffer the entire request/response on the server.

    The StreamBufferSize setting 64KB should be OK (although I would set it to truly 64KB == 64 * 1024). On the client, unless you have other requirements use the same buffer size, but I don't think it will matter than much.

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by cp.net Friday, November 30, 2012 8:18 PM
    Friday, November 30, 2012 7:34 AM
    Moderator

All replies

  • Service operations pass parameters in the URL. So your string will end up in a URL query option. Different HTTP components have different limits on the URL size, but in general these limits are pretty small (typically anything above cca 1000 characters will run into trouble). This can happen on the client (as you're seeing) or in between (proxies, caches, ...) or on the server (IIS has limits on this, WCF has others of its own and so on).

    So the general advice is - do not send large parameters to service operations.

    This can be "fixed" in two ways:

    1) Use Actions - WCF DS 5.0 (OData V3) introduces actions which behave very similarly to service operations, but they can take the parameters in the body of the request (as oppose to the URI).

    2) Model this part of the service as entity. So instead of sending a file as a parameter- create a new entity and send the file as its binary stream.

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by cp.net Friday, November 30, 2012 8:18 PM
    Thursday, November 29, 2012 4:39 PM
    Moderator
  • Thanks Vitek!

    I did go with the 2nd option, and got it streaming. For some reason, I thought calling a POST service operation from the client would not include the parameters in the URI. Can you please advise on some recommended service/binding settings so as to not run into Out-of-memory/data-threshold errors while streaming, and to get good speed? I'm working on a self-hosted WCF DS for an intranet environment. So far, these are the settings:

    For DataServiceHost:

    WebHttpBinding binding = new WebHttpBinding();
                binding.MaxReceivedMessageSize = int.MaxValue;
                binding.MaxBufferPoolSize = int.MaxValue;
                binding.MaxBufferSize = int.MaxValue;
                binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;

    For stream provider:

    int IDataServiceStreamProvider.StreamBufferSize
            {
                get { return 64000; }
            }

    Finally, is it a good idea to use same buffer size while performing Stream.Read(char[] buffer, int index, int count) on the Client?

    Appreciate it,

    cp

    Thursday, November 29, 2012 8:51 PM
  • In this article there's a good description of what needs to be set in WCF to make it truly streaming: http://msdn.microsoft.com/en-us/library/ee960144.aspx

    I think your setup above will allow large data but it will still buffer the entire request/response on the server.

    The StreamBufferSize setting 64KB should be OK (although I would set it to truly 64KB == 64 * 1024). On the client, unless you have other requirements use the same buffer size, but I don't think it will matter than much.

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by cp.net Friday, November 30, 2012 8:18 PM
    Friday, November 30, 2012 7:34 AM
    Moderator