2

I am iterating through a large list of objects (1503) and calling a save method on a ServiceProxy I have written. The service proxy uses the new networking stack in Silverlight 4 to call BeginGetRequestStream to start the process of asynchronously sending my objects to an azure REST service I have written for saving off the objects. The Http method I am using is POST. I know HttpWebClient is smart enough to reuse the Http connection so I am not concurrently opening 1503 connections to the server. Saving works fine and all 1503 objects are saved very quickly. However, when I try to save the same objects again, I expect to recieve an HttpStatus code of forbidden because the objects already exist and that is the code I set my azure web service to return. On small groups of objects, it works as expected. However, when I try saving the entire list of 1503 objects, I receive only 455 correct responses and 1048 errors such as "server not found" and

System.Exception ---> System.Exception:Error HRESULT E_FAIL has been returned from a call to a COM component.
at
System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)...

I wonder if there is some sort of book keeping or maintenance I am supposed to be performing on my HttpWebClient instances that I am neglecting and that is what is causing the http errors to throw exceptions but the new saves to work perfectly. Here is my code for handling the error cases:

private static void SendAncestorResponseCallback(IAsyncResult result)
    {
        var info = (SendAncestorInfo)result.AsyncState;

        try
        {
            var response = info.Request.EndGetResponse(result);
            info.Response = response;
        }
        catch ( Exception ex)
        {
            info.Error = ex;
        }

        info.MainThreadContext.Post(SendAncestorMainThreadCallback, info);
    }
    private static void SendAncestorMainThreadCallback(object state)
    {
        var info = (SendAncestorInfo)state;
        IAncestor origAncestor = info.Content;
        HttpWebResponse response = null;
        if (info.Error != null)
        {
            if ((info.Error as WebException) == null)
            {
                info.Callback(false, origAncestor, null, info.Error);
                return;
            }
            else //get response from WebException
            {
                response = (HttpWebResponse)(info.Error as WebException).Response;
            }
        }
        else  //get response from info.Response
        {
            response = info.Response as HttpWebResponse;
        } 
        if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.Forbidden)
        {
            var stream = response.GetResponseStream();
            using (var reader = new StreamReader(stream))
            {
                IAncestor retAncestor = XMLSerializerHelper.DeserializeObject<Ancestor>(reader.ReadToEnd());
                info.Callback(response.StatusCode == HttpStatusCode.Created, origAncestor, retAncestor, null);        
            }
        }
        else info.Callback(false, origAncestor, null, info.Error);
    }

considering how the web service is written I should only expect http status codes of created or forbidden and like I said with small groups this is the case. The fact that I only start getting the errors mentioned earlier makes me feel like I am doing something wrong with the HttpWebRequest objects etc. Any assistance would be greatly appreciated. Thanks.

--update here is the code that generates the HttpWebRequest:

foreach (IAncestor ancestor in ancestors)
            {
                AncestorViewModel ancestorVM = new AncestorViewModel(ancestor);
                ancestorVM.Status = SaveStatus.Undefined;
                ParsedAncestors.Add(ancestorVM);
                _service.CreateAncestor(UserSrc, ancestor, (success, origAncestor, retAncestor, exception) =>
                    {
                        AncestorViewModel result = ParsedAncestors.First(a => a.Model.IdNo == origAncestor.IdNo);
                        if (exception == null)//web response was either Created or Forbidden
                        {
                            if (success)//Ancestor successfully created
                            {
                                savedAncestors++;
                                SuccessMessage = string.Format("{0} Saved\n", savedAncestors);
                                result.Status = SaveStatus.Saved;
                            }
                            else //Ancestor already existed
                            {
                                conflictAncestors.Add(origAncestor, retAncestor);
                                ConflictMessage = string.Format("{0} Conflicts\n", conflictAncestors.Count);
                                result.Status = SaveStatus.Conflicted;
                            } 
                        }
                        else //Show exception recieved from remote web service
                        {
                            //if (exception as WebException != null)
                            //{
                            //    //if exception is WebException get status code and description
                            //    HttpWebResponse rs = (HttpWebResponse)(exception as WebException).Response;
                            //    Message += string.Format("WebServer returned status code {0}: '{1}'\n", (int)rs.StatusCode, rs.StatusDescription);
                            //}
                            errors.Add(origAncestor, exception);
                            ErrorMessage = string.Format("{0} Errors\n", errors.Count);
                            result.Status = SaveStatus.Error;
                        }
                    });
            }

public void CreateAncestor(string userSrc, IAncestor ancestor, Action<bool, IAncestor, IAncestor, Exception> callback)
    {
        WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
        var request = (HttpWebRequest)WebRequest.Create(
            new Uri(string.Format("{0}/{1}/{2}", rootUri, AncestorsRestPoint, userSrc)));
        request.Method = "POST";
        request.ContentType = "application/xml";
        var info = new SendAncestorInfo
        {
            Request = request,
            Callback = callback,
            Content = ancestor,
            MainThreadContext = SynchronizationContext.Current
        };

        request.BeginGetRequestStream(SendAncestorRequestCallback, info);
    }
Ben
  • 115
  • 10
  • Does your webservice require authentication? Can you copy your silverlight code, put it in a console mode app, and see if it works? ALso, can you post more code, ie how you are calling BeginGetResponse and where the HttpWebRequest is created? – feroze Nov 17 '10 at 03:17
  • Were you able to find a solution to this problem? – VoodooChild Nov 23 '10 at 18:46
  • no. I was able to tweak the service a little by turning off the nagle algorithm and searching for duplicates before I actually try adding a new entity and that dropped the number of errors significantly, but I still get around %20 of the items I try to add generating an HRESULT E_FAIL error. I did hook up Fiddler to try and see what is going on and the items that get the HRESULT E_FAIL never end up sending the request to the web service so I think the error comes from trying to view the httpwebresponse from a request that actually never happened. I don't know what it isn't happening though. – Ben Nov 27 '10 at 06:03

0 Answers0