コード例 #1
0
        /// <summary>
        /// Handler that the user will call when they want the request to resume processing.
        /// It will check to ensure that the correct WebRequest is passed back to this resumption point.
        /// Else an error will be thrown.
        /// </summary>
        /// <param name="request">HttpWebRequest for which the processing has to resume.</param>
        void ResumeRequestProcessing(HttpWebRequest request)
        {
            AsyncArgsWrapper wrapper = null;

            this._requestToArgsMapper.TryGetValue(request.GetHashCode(), out wrapper);
            if (wrapper == null)
            {
                // It means they called Resume with another WebRequest. Fail sync.
                throw new CacheControllerException("Incorrect HttpWebRequest object passed to ResumeRequestProcessing callback.");
            }

            try
            {
                this._requestToArgsMapper.Remove(request.GetHashCode());

                this.GetWebResponse(wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #2
0
        /// <summary>
        /// Check Metadata
        /// </summary>
        private void CheckEntityServiceMetadataAndTempIds(AsyncArgsWrapper wrapper, IOfflineEntity entity, string tempId)
        {
            // Check service ID
            if (string.IsNullOrEmpty(entity.GetServiceMetadata().Id))
            {
                throw new CacheControllerException(
                          string.Format("Service did not return a permanent Id for tempId '{0}'", tempId));
            }

            // If an entity has a temp id then it should not be a tombstone
            if (entity.GetServiceMetadata().IsTombstone)
            {
                throw new CacheControllerException(string.Format(
                                                       "Service returned a tempId '{0}' in tombstoned entity.", tempId));
            }

            // Check that the tempId was sent by client
            if (!wrapper.TempIdToEntityMapping.ContainsKey(tempId))
            {
                throw new CacheControllerException(
                          "Service returned a response for a tempId which was not uploaded by the client. TempId: " + tempId);
            }

            // Once received, remove the tempId from the mapping list.
            wrapper.TempIdToEntityMapping.Remove(tempId);
        }
コード例 #3
0
        /// <summary>
        /// Callback invoked when the cache request has been processed.
        /// </summary>
        /// <param name="state">AsyncArgsWrapper object</param>
        void CacheRequestCompleted(object state)
        {
            // Fire the ProcessCacheRequestCompleted handler
            AsyncArgsWrapper wrapper = state as AsyncArgsWrapper;

            if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
            {
                base.OnProcessCacheRequestCompleted(
                    new ProcessCacheRequestCompletedEventArgs(
                        wrapper.CacheRequest.RequestId,
                        wrapper.UploadResponse,
                        wrapper.Error,
                        wrapper.UserPassedState)
                    );
            }
            else
            {
                base.OnProcessCacheRequestCompleted(
                    new ProcessCacheRequestCompletedEventArgs(
                        wrapper.CacheRequest.RequestId,
                        wrapper.DownloadResponse,
                        wrapper.Error,
                        wrapper.UserPassedState)
                    );
            }
        }
コード例 #4
0
        /// <summary>
        /// Issues the BeginGetResponse call for the HttpWebRequest
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        private void GetWebResponse(AsyncArgsWrapper wrapper)
        {
            var requestData = new TimeoutRequestData()
            {
                Request = wrapper.WebRequest
            };

            // Send the request and wait for the response.
            if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
            {
                lock (_timeoutSync)
                {
                    IAsyncResult resultUpload = wrapper.WebRequest.BeginGetResponse(OnUploadGetResponseCompleted, wrapper);
                    requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultUpload.AsyncWaitHandle,
                                                                                new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                }
            }
            else
            {
                lock (_timeoutSync)
                {
                    IAsyncResult resultDownload = wrapper.WebRequest.BeginGetResponse(OnDownloadGetResponseCompleted, wrapper);
                    requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultDownload.AsyncWaitHandle,
                                                                                new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream
        /// </summary>
        private void WriteDownloadRequestStream(Stream requestStream, AsyncArgsWrapper wrapper)
        {
            try
            {
                // Create a SyncWriter to write the contents
                var syncWriter = (SerializationFormat == SerializationFormat.ODataAtom)
                    ? new ODataAtomWriter(BaseUri)
                    : (SyncWriter) new ODataJsonWriter(BaseUri);

                //syncWriter = new ODataAtomWriter(BaseUri);

                syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                if (SerializationFormat == SerializationFormat.ODataAtom)
                {
                    syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    syncWriter.WriteFeed(new XmlJsonWriter(requestStream));
                }

                requestStream.Flush();
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
            }
        }
コード例 #6
0
        private IEnumerable <IsolatedStorageOfflineEntity> GetDownloadedValues(AsyncArgsWrapper wrapper)
        {
            while (this._syncReader.Next())
            {
                switch (_syncReader.ItemType)
                {
                case ReaderItemType.Entry:
                    IsolatedStorageOfflineEntity offlineEntity = _syncReader.GetItem();
                    var entity = offlineEntity as IEntity;
                    if (entity != null)
                    {
                        LogManager.Logger.SyncDownload(entity.EntityType, offlineEntity.ServiceMetadata.IsTombstone);
                    }
                    yield return(offlineEntity);

                    break;

                case ReaderItemType.SyncBlob:
                    wrapper.DownloadResponse.ServerBlob = _syncReader.GetServerBlob();
                    break;

                case ReaderItemType.HasMoreChanges:
                    wrapper.DownloadResponse.IsLastBatch = !_syncReader.GetHasMoreChangesValue();
                    break;
                }
            }
            _syncReader.Dispose();
        }
コード例 #7
0
 /// <summary>
 /// Invokes the user's AfterReceivingResponse callback.
 /// </summary>
 /// <param name="wrapper">AsyncArgsWrapper object</param>
 void FirePostResponseHandler(AsyncArgsWrapper wrapper)
 {
     if (this._afterResponseHandler != null)
     {
         // Invoke the user code.
         this._afterResponseHandler(wrapper.WebResponse);
     }
 }
コード例 #8
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.beginGetRequestStream
        /// </summary>
        private void WriteUploadRequestStream(Stream requestStream, AsyncArgsWrapper wrapper)
        {
            try
            {
                // Create a SyncWriter to write the contents
                this.syncWriter = (SerializationFormat == SerializationFormat.ODataAtom)
                    ? new ODataAtomWriter(BaseUri)
                    : (SyncWriter) new ODataJsonWriter(BaseUri);


                syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                foreach (IOfflineEntity entity in wrapper.CacheRequest.Changes)
                {
                    // Skip tombstones that dont have a ID element.
                    if (entity.GetServiceMetadata().IsTombstone&& string.IsNullOrEmpty(entity.GetServiceMetadata().Id))
                    {
                        continue;
                    }

                    string tempId = null;

                    // Check to see if this is an insert. i.e ServiceMetadata.Id is null or empty
                    if (string.IsNullOrEmpty(entity.GetServiceMetadata().Id))
                    {
                        if (wrapper.TempIdToEntityMapping == null)
                        {
                            wrapper.TempIdToEntityMapping = new Dictionary <string, IOfflineEntity>();
                        }

                        tempId = Guid.NewGuid().ToString();
                        wrapper.TempIdToEntityMapping.Add(tempId, entity);
                    }

                    syncWriter.AddItem(entity, tempId);
                }

                if (SerializationFormat == SerializationFormat.ODataAtom)
                {
                    syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this.syncWriter.WriteFeed(new XmlJsonWriter(requestStream));
                }

                requestStream.Flush();
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
            }
        }
コード例 #9
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream. Deserializes the response feed to
        /// retrieve the list of IOfflineEntity objects and constructs an ChangeSet for that.
        /// </summary>
        private async Task ReadDownloadResponse(HttpWebResponse response, AsyncArgsWrapper wrapper)
        {
            try
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    using (Stream responseStream = GetWrappedStream(response))
                    {
                        // Create the SyncReader
                        using (var syncReader = (SerializationFormat == SerializationFormat.ODataAtom)
                            ? new ODataAtomReader(responseStream, this.knownTypes)
                            : (SyncReader) new ODataJsonReader(responseStream, this.knownTypes))
                        {
                            await Task.Factory.StartNew(() =>
                            {
                                // Read the response
                                while (syncReader.Next())
                                {
                                    switch (syncReader.ItemType)
                                    {
                                    case ReaderItemType.Entry:
                                        wrapper.DownloadResponse.AddItem(syncReader.GetItem());
                                        break;

                                    case ReaderItemType.SyncBlob:
                                        wrapper.DownloadResponse.ServerBlob = syncReader.GetServerBlob();
                                        // Debug.WriteLine(SyncBlob.DeSerialize(wrapper.DownloadResponse.ServerBlob).ToString());
                                        break;

                                    case ReaderItemType.HasMoreChanges:
                                        wrapper.DownloadResponse.IsLastBatch = !syncReader.GetHasMoreChangesValue();
                                        break;
                                    }
                                }
                            });
                        }
                    }
                }
                else
                {
                    wrapper.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
            }
        }
 /// <summary>
 /// Issues the BeginGetResponse call for the HttpWebRequest
 /// </summary>
 /// <param name="wrapper">AsyncArgsWrapper object</param>
 private void GetWebResponse(AsyncArgsWrapper wrapper)
 {
     // Send the request and wait for the response.
     if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
     {
         wrapper.WebRequest.BeginGetResponse(OnUploadGetResponseCompleted, wrapper);
     }
     else
     {
         wrapper.WebRequest.BeginGetResponse(OnDownloadGetResponseCompleted, wrapper);
     }
 }
コード例 #11
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream
        /// </summary>
        /// <param name="asyncResult">IAsyncResult object</param>
        void OnDownloadGetRequestStreamCompleted(IAsyncResult asyncResult)
        {
            AsyncArgsWrapper wrapper = asyncResult.AsyncState as AsyncArgsWrapper;

            try
            {
                Stream requestStream = wrapper.WebRequest.EndGetRequestStream(asyncResult);

                // CreateInstance a SyncWriter to write the contents
                if (ApplicationContext.Current.Settings.BitMobileFormatterDisabled)
                {
                    _syncWriter = new ODataAtomWriter(BaseUri);
                }
                else
                {
                    _syncWriter = new BMWriter(BaseUri);
                }


                this._syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                if (base.SerializationFormat == SerializationFormat.ODataAtom)
                {
                    this._syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this._syncWriter.WriteFeed(JsonReaderWriterFactory.CreateJsonWriter(requestStream));
                }

                requestStream.Flush();
                requestStream.Close();

                if (this._beforeRequestHandler != null)
                {
                    // Invoke user code and wait for them to call back us when they are done with the input request
                    this._workerManager.PostProgress(wrapper.WorkerRequest, this.FirePreRequestHandler, wrapper);
                }
                else
                {
                    this.GetWebResponse(wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #12
0
 /// <summary>
 /// Issues the BeginGetResponse call for the HttpWebRequest
 /// </summary>
 /// <param name="wrapper">AsyncArgsWrapper object</param>
 private async Task GetWebResponse(AsyncArgsWrapper wrapper)
 {
     // Send the request and wait for the response.
     if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
     {
         var task = wrapper.WebRequest.GetResponseAsync();
         await OnUploadGetResponseCompleted(task, wrapper).ConfigureAwait(false);
     }
     else
     {
         var task = wrapper.WebRequest.GetResponseAsync();
         await OnDownloadGetResponseCompleted(task, wrapper).ConfigureAwait(false);
     }
 }
コード例 #13
0
        void ProcessCacheRequestWorker(AsyncWorkRequest worker, object[] inputParams)
        {
            CacheRequest request = inputParams [0] as CacheRequest;
            object       state   = inputParams [1];

            _wrapper = new AsyncArgsWrapper()
            {
                UserPassedState = state,
                WorkerRequest   = worker,
                CacheRequest    = request
            };

            ProcessRequest();
        }
コード例 #14
0
        /// <summary>
        /// Actual worker performing the work
        /// </summary>
        /// <param name="worker">AsyncWorkRequest object</param>
        /// <param name="inputParams">input parameters</param>
        void ProcessCacheRequestWorker(AsyncWorkRequest worker, object[] inputParams)
        {
            Debug.Assert(inputParams.Length == 2);

            CacheRequest request = inputParams[0] as CacheRequest;
            object       state   = inputParams[1];

            AsyncArgsWrapper wrapper = new AsyncArgsWrapper()
            {
                UserPassedState = state,
                WorkerRequest   = worker,
                CacheRequest    = request
            };

            ProcessRequest(wrapper);
        }
コード例 #15
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream
        /// </summary>
        /// <param name="task">Task representing the future request stream</param>
        async Task OnDownloadGetRequestStreamCompleted(Task <Stream> task, AsyncArgsWrapper wrapper)
        {
            try
            {
                Stream requestStream = await task.ConfigureAwait(false);

                // Create a SyncWriter to write the contents
                this._syncWriter = (base.SerializationFormat == SerializationFormat.ODataAtom)
                    ? (SyncWriter) new ODataAtomWriter(base.BaseUri)
                    : (SyncWriter) new ODataJsonWriter(base.BaseUri);

                this._syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                if (base.SerializationFormat == SerializationFormat.ODataAtom)
                {
                    this._syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this._syncWriter.WriteFeed(JsonReaderWriterFactory.CreateJsonWriter(requestStream));
                }

                requestStream.Flush();
                requestStream.Close();

                if (this._beforeRequestHandler != null)
                {
                    // Invoke user code and wait for them to call back us when they are done with the input request
                    this._workerManager.PostProgress(wrapper.WorkerRequest, this.FirePreRequestHandler, wrapper);
                }
                else
                {
                    this.GetWebResponse(wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #16
0
        /// <summary>
        /// Called by the CacheController when it wants this CacheRequest to be processed asynchronously.
        /// </summary>
        /// <param name="request">CacheRequest to be processed</param>
        /// <param name="state">User state object</param>
        /// <param name="cancellationToken"> </param>
        public async Task <CacheRequestResult> ProcessCacheRequestAsync(CacheRequest request, object state,
                                                                        CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }

            var wrapper = new AsyncArgsWrapper
            {
                UserPassedState = state,
                CacheRequest    = request,
                Step            = HttpState.Start
            };

            wrapper = await ProcessRequest(wrapper, cancellationToken);

            CacheRequestResult cacheRequestResult;

            if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
            {
                cacheRequestResult =
                    new CacheRequestResult(
                        wrapper.CacheRequest.RequestId,
                        wrapper.UploadResponse,
                        wrapper.CacheRequest.Changes.Count,
                        wrapper.Error,
                        wrapper.Step,
                        wrapper.UserPassedState);
            }
            else
            {
                cacheRequestResult =
                    new CacheRequestResult(
                        wrapper.CacheRequest.RequestId,
                        wrapper.DownloadResponse,
                        wrapper.Error,
                        wrapper.Step,
                        wrapper.UserPassedState);
            }
            return(cacheRequestResult);
        }
コード例 #17
0
        /// <summary>
        /// Called by the CacheController when it wants this CacheRequest to be processed asynchronously.
        /// </summary>
        /// <param name="request">CacheRequest to be processed</param>
        /// <param name="state">User state object</param>
        /// <param name="cancellationToken"> </param>
        public async Task<CacheRequestResult> ProcessCacheRequestAsync(CacheRequest request, object state,
                                                                       CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
                cancellationToken.ThrowIfCancellationRequested();

            var wrapper = new AsyncArgsWrapper
            {
                UserPassedState = state,
                CacheRequest = request,
                Step = HttpState.Start
            };

            wrapper = await ProcessRequest(wrapper, cancellationToken);

            CacheRequestResult cacheRequestResult;

            if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
            {
                cacheRequestResult =
                    new CacheRequestResult(
                        wrapper.CacheRequest.RequestId,
                        wrapper.UploadResponse,
                        wrapper.CacheRequest.Changes.Count,
                        wrapper.Error,
                        wrapper.Step,
                        wrapper.UserPassedState);
            }
            else
            {
                cacheRequestResult =
                    new CacheRequestResult(
                        wrapper.CacheRequest.RequestId,
                        wrapper.DownloadResponse,
                        wrapper.Error,
                        wrapper.Step,
                        wrapper.UserPassedState);
            }
            return cacheRequestResult;
        }
コード例 #18
0
        /// <summary>
        /// Invokes the user BeforeSendingRequest callback. It also passes the resumption handler for the user
        /// to call when they are done with the customizations on the request.
        /// </summary>
        /// <param name="state">Async user state object. Ignored.</param>
        void FirePreRequestHandler(object state)
        {
            AsyncArgsWrapper wrapper = state as AsyncArgsWrapper;

            try
            {
                // Add this to the requestToArgs mapper so we can look up the args when the user calls ResumeRequestProcessing
                this._requestToArgsMapper[wrapper.WebRequest.GetHashCode()] = wrapper;

                // Invoke the user code.
                this._beforeRequestHandler(wrapper.WebRequest, ResumeRequestProcessing);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #19
0
        /// <summary>
        /// Method that does the actual processing. 
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        /// <param name="cancellationToken"> </param>
        private async Task<AsyncArgsWrapper> ProcessRequest(AsyncArgsWrapper wrapper,
                                                            CancellationToken cancellationToken)
        {
            HttpWebResponse webResponse = null;
            try
            {
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                var requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                                        BaseUri,
                                        (BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                                        Uri.EscapeUriString(ScopeName),
                                        wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (var kvp in scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key),
                                            Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                        prefix = "&";
                }

                // Create the WebRequest
                HttpWebRequest webRequest;

                if (credentials != null)
                {
                    // Create the Client Http request
                    webRequest = WebRequest.CreateHttp(new Uri(requestUri.ToString()));
                    // Add credentials
                    webRequest.Credentials = credentials;
                }
                else
                {
                    // Use WebRequest.Create the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString());
                }

                // set cookies if exists
                if (CookieContainer != null)
                    webRequest.CookieContainer = CookieContainer;

                // Set the method type
                webRequest.Method = "POST";
                webRequest.Accept = (SerializationFormat == SerializationFormat.ODataAtom)
                                        ? "application/atom+xml"
                                        : "application/json";
                webRequest.ContentType = (SerializationFormat == SerializationFormat.ODataAtom)
                                             ? "application/atom+xml"
                                             : "application/json";
#if !WINDOWS_PHONE
                if (automaticDecompression)
                {
                    webRequest.Headers["Accept-Encoding"] = "gzip, deflated";
                }
#endif
                foreach (var kvp in customHeaders)
                {
                    webRequest.Headers[kvp.Key] = kvp.Value;
                }
                // To be sure where it could be raise an error, just mark the step
                wrapper.Step = HttpState.WriteRequest;

#if !NETFX_CORE
                using (Stream stream = await Task.Factory.FromAsync<Stream>(
                                    webRequest.BeginGetRequestStream,
                                    webRequest.EndGetRequestStream, null))
#else
                using (Stream stream = await webRequest.GetRequestStreamAsync())
#endif
                {
                    if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                        WriteUploadRequestStream(stream, wrapper);
                    else
                        WriteDownloadRequestStream(stream, wrapper);
                }

                // If error, return wrapper with error
                if (wrapper.Error != null)
                    return wrapper;

                // Get Response
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                    wrapper.UploadResponse = new ChangeSetResponse();
                else
                    wrapper.DownloadResponse = new ChangeSet();

                wrapper.Step = HttpState.ReadResponse;

#if !NETFX_CORE
                webResponse = (HttpWebResponse)(await Task.Factory.FromAsync<WebResponse>(
                                                webRequest.BeginGetResponse,
                                                webRequest.EndGetResponse, null));
#else
                webResponse = (HttpWebResponse)(await webRequest.GetResponseAsync());
#endif

                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                    await ReadUploadResponse(webResponse, wrapper);
                else
                    await ReadDownloadResponse(webResponse, wrapper);

                if (webResponse != null)
                {
                    wrapper.Step = HttpState.End;
                    webResponse.Dispose();
                    webResponse = null;
                }
            }
            catch (WebException we)
            {
               // if (we.Response == null)
               // {
                   // default to this, there will be cases where the we.Response is != null but the content length = 0
                   // e.g 413 and other server errors. e.g the else branch of reader.ReadToDescendent. By defaulting to this
                   // we always capture the error rather then returning an error of null in some cases
                    wrapper.Error = we;
                //}

                if(we.Response != null)
                {
                    using (var stream = GetWrappedStream(we.Response))
                    {
                        using (var reader = SerializationFormat == SerializationFormat.ODataAtom ?
                            XmlReader.Create(stream) :
                            new XmlJsonReader(stream, XmlDictionaryReaderQuotas.Max))
                        {
                            if (reader.ReadToDescendant(FormatterConstants.ErrorDescriptionElementNamePascalCasing))
                            {
                                wrapper.Error = new Exception(reader.ReadElementContentAsString());
                            }
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                    throw;

                wrapper.Error = e;
                return wrapper;
            }

            return wrapper;
        }
コード例 #20
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.beginGetRequestStream
        /// </summary>
        private void WriteUploadRequestStream(Stream requestStream, AsyncArgsWrapper wrapper)
        {
            try
            {
                // Create a SyncWriter to write the contents
                var syncWriter = (SerializationFormat == SerializationFormat.ODataAtom)
                    ? new ODataAtomWriter(BaseUri)
                    : (SyncWriter)new ODataJsonWriter(BaseUri);

                syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                foreach (IOfflineEntity entity in wrapper.CacheRequest.Changes)
                {
                    // Skip tombstones that dont have a ID element.
                    if (entity.GetServiceMetadata().IsTombstone && string.IsNullOrEmpty(entity.GetServiceMetadata().Id))
                        continue;

                    string tempId = null;

                    // Check to see if this is an insert. i.e ServiceMetadata.Id is null or empty
                    if (string.IsNullOrEmpty(entity.GetServiceMetadata().Id))
                    {
                        if (wrapper.TempIdToEntityMapping == null)
                            wrapper.TempIdToEntityMapping = new Dictionary<string, IOfflineEntity>();

                        tempId = Guid.NewGuid().ToString();
                        wrapper.TempIdToEntityMapping.Add(tempId, entity);
                    }

                    syncWriter.AddItem(entity, tempId);
                }

                if (SerializationFormat == SerializationFormat.ODataAtom)
                    syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                else
                    syncWriter.WriteFeed(new XmlJsonWriter(requestStream));

                requestStream.Flush();
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
            }
        }
コード例 #21
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.BeginGetResponse call
        /// </summary>
        private async Task ReadUploadResponse(HttpWebResponse response, AsyncArgsWrapper wrapper)
        {
            try
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    using (Stream responseStream = GetWrappedStream(response))
                    {
                        using (var syncReader = (SerializationFormat == SerializationFormat.ODataAtom)
                            ? new ODataAtomReader(responseStream, this.knownTypes)
                            : (SyncReader) new ODataJsonReader(responseStream, this.knownTypes))
                        {
                            // Read the response
                            await Task.Factory.StartNew(() =>
                            {
                                while (syncReader.Next())
                                {
                                    switch (syncReader.ItemType)
                                    {
                                    case ReaderItemType.Entry:
                                        IOfflineEntity entity      = syncReader.GetItem();
                                        IOfflineEntity ackedEntity = entity;
                                        string tempId = null;

                                        // If conflict only one temp ID should be set
                                        if (syncReader.HasTempId() && syncReader.HasConflictTempId())
                                        {
                                            throw new CacheControllerException(
                                                string.Format(
                                                    "Service returned a TempId '{0}' in both live and conflicting entities.",
                                                    syncReader.GetTempId()));
                                        }

                                        // Validate the live temp ID if any, before adding anything to the offline context
                                        if (syncReader.HasTempId())
                                        {
                                            tempId = syncReader.GetTempId();
                                            CheckEntityServiceMetadataAndTempIds(wrapper, entity, tempId);
                                        }

                                        //  If conflict
                                        if (syncReader.HasConflict())
                                        {
                                            Conflict conflict             = syncReader.GetConflict();
                                            IOfflineEntity conflictEntity = (conflict is SyncConflict)
                                                                                    ? ((SyncConflict)conflict).LosingEntity
                                                                                    : ((SyncError)conflict).ErrorEntity;

                                            // Validate conflict temp ID if any
                                            if (syncReader.HasConflictTempId())
                                            {
                                                tempId = syncReader.GetConflictTempId();
                                                CheckEntityServiceMetadataAndTempIds(wrapper, conflictEntity, tempId);
                                            }

                                            // Add conflict
                                            wrapper.UploadResponse.AddConflict(conflict);

                                            //
                                            // If there is a conflict and the tempId is set in the conflict entity then the client version lost the
                                            // conflict and the live entity is the server version (ServerWins)
                                            //
                                            if (syncReader.HasConflictTempId() && entity.GetServiceMetadata().IsTombstone)
                                            {
                                                //
                                                // This is a ServerWins conflict, or conflict error. The winning version is a tombstone without temp Id
                                                // so there is no way to map the winning entity with a temp Id. The temp Id is in the conflict so we are
                                                // using the conflict entity, which has the PK, to build a tombstone entity used to update the offline context
                                                //
                                                // In theory, we should copy the service metadata but it is the same end result as the service fills in
                                                // all the properties in the conflict entity
                                                //

                                                // Add the conflict entity
                                                conflictEntity.GetServiceMetadata().IsTombstone = true;
                                                ackedEntity = conflictEntity;
                                            }
                                        }

                                        // Add ackedEntity to storage. If ackedEntity is still equal to entity then add non-conflict entity.
                                        if (!String.IsNullOrEmpty(tempId))
                                        {
                                            wrapper.UploadResponse.AddUpdatedItem(ackedEntity);
                                        }
                                        break;

                                    case ReaderItemType.SyncBlob:
                                        wrapper.UploadResponse.ServerBlob = syncReader.GetServerBlob();
                                        break;
                                    }
                                }
                            });


                            if (wrapper.TempIdToEntityMapping != null && wrapper.TempIdToEntityMapping.Count != 0)
                            {
                                // The client sent some inserts which werent ack'd by the service. Throw.
                                var builder =
                                    new StringBuilder(
                                        "Server did not acknowledge with a permanent Id for the following tempId's: ");
                                builder.Append(string.Join(",", wrapper.TempIdToEntityMapping.Keys.ToArray()));
                                throw new CacheControllerException(builder.ToString());
                            }
                        }
                    }
                }
                else
                {
                    wrapper.UploadResponse.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
            }
        }
コード例 #22
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream. Deserializes the response feed to
        /// retrieve the list of IOfflineEntity objects and constructs an ChangeSet for that.
        /// </summary>
        private async Task ReadDownloadResponse(HttpWebResponse response, AsyncArgsWrapper wrapper)
        {
            try
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    using (Stream responseStream = GetWrappedStream(response))
                    {


                        // Create the SyncReader
                        using (var syncReader = (SerializationFormat == SerializationFormat.ODataAtom)
                            ? new ODataAtomReader(responseStream, this.knownTypes)
                            : (SyncReader)new ODataJsonReader(responseStream, this.knownTypes))
                        {

                            await Task.Factory.StartNew(() =>
                            {
                                // Read the response
                                while (syncReader.Next())
                                {
                                    switch (syncReader.ItemType)
                                    {
                                        case ReaderItemType.Entry:
                                            wrapper.DownloadResponse.AddItem(syncReader.GetItem());
                                            break;
                                        case ReaderItemType.SyncBlob:
                                            wrapper.DownloadResponse.ServerBlob = syncReader.GetServerBlob();
                                            // Debug.WriteLine(SyncBlob.DeSerialize(wrapper.DownloadResponse.ServerBlob).ToString());
                                            break;
                                        case ReaderItemType.HasMoreChanges:
                                            wrapper.DownloadResponse.IsLastBatch = !syncReader.GetHasMoreChangesValue();
                                            break;
                                    }
                                }

                            });

                        }
                    }
                }
                else
                {
                    wrapper.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
            }
        }
コード例 #23
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream. Deserializes the response feed to
        /// retrieve the list of IOfflineEntity objects and constructs an ChangeSet for that.
        /// </summary>
        /// <param name="asyncResult">IAsyncResult object</param>
        void OnDownloadGetResponseCompleted(IAsyncResult asyncResult)
        {
            AsyncArgsWrapper wrapper = asyncResult.AsyncState as AsyncArgsWrapper;

            wrapper.DownloadResponse = new ChangeSet();

            HttpWebResponse response = null;

            try
            {
                try
                {
                    response = wrapper.WebRequest.EndGetResponse(asyncResult) as HttpWebResponse;
                    if (String.IsNullOrEmpty(behaviors.UserId))
                    {
                        behaviors.UserId = response.Headers["userid"];
                    }
                    if (string.IsNullOrWhiteSpace(behaviors.UserEmail))
                    {
                        behaviors.UserEmail = response.Headers["email"];
                    }
                    behaviors.ResourceVersion = response.Headers["resourceversion"];
                }
                catch (WebException we)
                {
                    wrapper.Error = we;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }
                catch (SecurityException se)
                {
                    wrapper.Error = se;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    behaviors.SaveUserSession();

                    int contentLength = (int)response.ContentLength;

                    if (response.Headers.AllKeys.Contains("unzippedcontentlength"))
                    {
                        string value = response.Headers["unzippedcontentlength"];
                        if (!int.TryParse(value, out contentLength))
                        {
                            throw new WebException("Invalid value of header unzippedcontentlength: " + value);
                        }
                    }

                    Stream responseStream = new ProgressStream(response.GetResponseStream()
                                                               , contentLength
                                                               , behaviors.ReadProgressCallback);

                    // CreateInstance the SyncReader
                    if (ApplicationContext.Current.Settings.BitMobileFormatterDisabled)
                    {
                        _syncReader = new ODataAtomReader(responseStream, _knownTypes);
                    }
                    else
                    {
                        _syncReader = new BMReader(responseStream, _knownTypes);
                    }

                    // Read the response
                    wrapper.DownloadResponse.Data = GetDownloadedValues(wrapper);

                    wrapper.WebResponse = response;
                    // Invoke user code on the correct synchronization context.
                    this.FirePostResponseHandler(wrapper);
                }
                else
                {
                    wrapper.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }

                // If we get here then it means we completed the request. Return to the original caller
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #24
0
        /// <summary>
        /// Method that does the actual processing. 
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        void ProcessRequest(AsyncArgsWrapper wrapper)
        {
            try
            {
                StringBuilder requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                                         base.BaseUri,
                                         (base.BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                                         Uri.EscapeUriString(base.ScopeName),
                                         wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (KeyValuePair<string, string> kvp in this._scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key), Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                    {
                        prefix = "&";
                    }
                }

                //requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString("user"), Uri.EscapeUriString("test"));
                //requestUri.AppendFormat("{0}{1}={2}", "&", Uri.EscapeUriString("pwd"), Uri.EscapeUriString("test"));

                // CreateInstance the WebRequest
                HttpWebRequest webRequest = null;

                if (this._credentials != null)
                {
                    // CreateInstance the Client Http request
                    //webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.CreateInstance(new Uri(requestUri.ToString()));
                    webRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri(requestUri.ToString().ToCurrentScheme(ApplicationContext.Current.Settings.HttpsDisabled)));

                    NetworkCredential credential = this._credentials.GetCredential(BaseUri, "Basic");

                    // Add credentials
                    webRequest.Credentials = this._credentials;

                    string svcCredentials =
                        Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(credential.UserName + ":" + credential.Password));
                    webRequest.Headers.Add("Authorization", "Basic " + svcCredentials);

                    webRequest.Headers.Add("configname:" + behaviors.ConfigName);
                    webRequest.Headers.Add("configversion:" + behaviors.ConfigVersion);

                    webRequest.Headers.Add("coreversion", behaviors.CoreVersion.ToString());
                }
                else
                {
                    // Use WebRequest.CreateInstance the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString().ToCurrentScheme(ApplicationContext.Current.Settings.HttpsDisabled));
                }

                foreach (var item in behaviors.DeviceInfo)
                    webRequest.Headers.Add(item.Key, item.Value);

                webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
                webRequest.Timeout = 5000;

                // Set the method type
                //webRequest.Timeout = 10;
                //webRequest.ReadWriteTimeout = 10;
                webRequest.Method = "POST";
                webRequest.Accept = ApplicationContext.Current.Settings.BitMobileFormatterDisabled ? "application/atom+xml" : "application/bitmobile";
                webRequest.ContentType = ApplicationContext.Current.Settings.BitMobileFormatterDisabled ? "application/atom+xml" : "application/bitmobile";

                wrapper.WebRequest = webRequest;

                var requestData = new TimeoutRequestData()
                {
                    Request = wrapper.WebRequest
                };

                // Get the request stream
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    lock (_timeoutSync)
                    {
                        IAsyncResult resultUpload = webRequest.BeginGetRequestStream(OnUploadGetRequestStreamCompleted, wrapper);
                        requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultUpload.AsyncWaitHandle,
                            new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                    }
                }
                else
                {
                    lock (_timeoutSync)
                    {
                        IAsyncResult resultDownload = webRequest.BeginGetRequestStream(OnDownloadGetRequestStreamCompleted, wrapper);
                        requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultDownload.AsyncWaitHandle,
                            new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                    }
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #25
0
 /// <summary>
 /// Issues the BeginGetResponse call for the HttpWebRequest
 /// </summary>
 /// <param name="wrapper">AsyncArgsWrapper object</param>
 private async Task GetWebResponse(AsyncArgsWrapper wrapper)
 {
     // Send the request and wait for the response.
     if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
     {
         var task = wrapper.WebRequest.GetResponseAsync();
         await OnUploadGetResponseCompleted(task, wrapper).ConfigureAwait(false);
     }
     else
     {
         var task = wrapper.WebRequest.GetResponseAsync();
         await OnDownloadGetResponseCompleted(task, wrapper).ConfigureAwait(false);
     }
 }
コード例 #26
0
        /// <summary>
        /// Method that does the actual processing.
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        void ProcessRequest(AsyncArgsWrapper wrapper)
        {
            try
            {
                StringBuilder requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                                        base.BaseUri,
                                        (base.BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                                        Uri.EscapeUriString(base.ScopeName),
                                        wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (KeyValuePair <string, string> kvp in this._scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key), Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                    {
                        prefix = "&";
                    }
                }

                //requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString("user"), Uri.EscapeUriString("test"));
                //requestUri.AppendFormat("{0}{1}={2}", "&", Uri.EscapeUriString("pwd"), Uri.EscapeUriString("test"));

                // CreateInstance the WebRequest
                HttpWebRequest webRequest = null;

                if (this._credentials != null)
                {
                    // CreateInstance the Client Http request
                    //webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.CreateInstance(new Uri(requestUri.ToString()));
                    webRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri(requestUri.ToString().ToCurrentScheme(ApplicationContext.Current.Settings.HttpsDisabled)));

                    NetworkCredential credential = this._credentials.GetCredential(BaseUri, "Basic");

                    // Add credentials
                    webRequest.Credentials = this._credentials;

                    string svcCredentials =
                        Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(credential.UserName + ":" + credential.Password));
                    webRequest.Headers.Add("Authorization", "Basic " + svcCredentials);

                    webRequest.Headers.Add("configname:" + behaviors.ConfigName);
                    webRequest.Headers.Add("configversion:" + behaviors.ConfigVersion);

                    webRequest.Headers.Add("coreversion", behaviors.CoreVersion.ToString());
                }
                else
                {
                    // Use WebRequest.CreateInstance the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString().ToCurrentScheme(ApplicationContext.Current.Settings.HttpsDisabled));
                }

                foreach (var item in behaviors.DeviceInfo)
                {
                    webRequest.Headers.Add(item.Key, item.Value);
                }

                webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
                webRequest.Timeout = 5000;

                // Set the method type
                //webRequest.Timeout = 10;
                //webRequest.ReadWriteTimeout = 10;
                webRequest.Method      = "POST";
                webRequest.Accept      = ApplicationContext.Current.Settings.BitMobileFormatterDisabled ? "application/atom+xml" : "application/bitmobile";
                webRequest.ContentType = ApplicationContext.Current.Settings.BitMobileFormatterDisabled ? "application/atom+xml" : "application/bitmobile";

                wrapper.WebRequest = webRequest;

                var requestData = new TimeoutRequestData()
                {
                    Request = wrapper.WebRequest
                };

                // Get the request stream
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    lock (_timeoutSync)
                    {
                        IAsyncResult resultUpload = webRequest.BeginGetRequestStream(OnUploadGetRequestStreamCompleted, wrapper);
                        requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultUpload.AsyncWaitHandle,
                                                                                    new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                    }
                }
                else
                {
                    lock (_timeoutSync)
                    {
                        IAsyncResult resultDownload = webRequest.BeginGetRequestStream(OnDownloadGetRequestStreamCompleted, wrapper);
                        requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultDownload.AsyncWaitHandle,
                                                                                    new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                    }
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #27
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.beginGetRequestStream
        /// </summary>
        /// <param name="task">Task representing the future request stream</param>
        async Task OnUploadGetRequestStreamCompleted(Task<Stream> task, AsyncArgsWrapper wrapper)
        {
            try
            {
                Stream requestStream = await task.ConfigureAwait(false);

                // Create a SyncWriter to write the contents
                this._syncWriter = (base.SerializationFormat == SerializationFormat.ODataAtom)
                    ? (SyncWriter)new ODataAtomWriter(base.BaseUri)
                    : (SyncWriter)new ODataJsonWriter(base.BaseUri);

                this._syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                foreach (IOfflineEntity entity in wrapper.CacheRequest.Changes)
                {
                    // Skip tombstones that dont have a ID element.
                    if (entity.ServiceMetadata.IsTombstone && string.IsNullOrEmpty(entity.ServiceMetadata.Id))
                    {
                        continue;
                    }

                    string tempId = null;

                    // Check to see if this is an insert. i.e ServiceMetadata.Id is null or empty
                    if (string.IsNullOrEmpty(entity.ServiceMetadata.Id))
                    {
                        if (wrapper.TempIdToEntityMapping == null)
                        {
                            wrapper.TempIdToEntityMapping = new Dictionary<string, IOfflineEntity>();
                        }
                        tempId = Guid.NewGuid().ToString();
                        wrapper.TempIdToEntityMapping.Add(tempId, entity);
                    }

                    this._syncWriter.AddItem(entity, tempId);
                }

                if (base.SerializationFormat == SerializationFormat.ODataAtom)
                {
                    this._syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this._syncWriter.WriteFeed(JsonReaderWriterFactory.CreateJsonWriter(requestStream));
                }

                requestStream.Flush();
                requestStream.Close();

                if (this._beforeRequestHandler != null)
                {
                    // Invoke user code and wait for them to call back us when they are done with the input request
                    this._workerManager.PostProgress(wrapper.WorkerRequest, this.FirePreRequestHandler, wrapper);
                }
                else
                {
                    this.GetWebResponse(wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #28
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.beginGetRequestStream
        /// </summary>
        /// <param name="task">Task representing the future request stream</param>
        async Task OnUploadGetRequestStreamCompleted(Task <Stream> task, AsyncArgsWrapper wrapper)
        {
            try
            {
                Stream requestStream = await task.ConfigureAwait(false);

                // Create a SyncWriter to write the contents
                this._syncWriter = (base.SerializationFormat == SerializationFormat.ODataAtom)
                    ? (SyncWriter) new ODataAtomWriter(base.BaseUri)
                    : (SyncWriter) new ODataJsonWriter(base.BaseUri);

                this._syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                foreach (IOfflineEntity entity in wrapper.CacheRequest.Changes)
                {
                    // Skip tombstones that dont have a ID element.
                    if (entity.ServiceMetadata.IsTombstone && string.IsNullOrEmpty(entity.ServiceMetadata.Id))
                    {
                        continue;
                    }

                    string tempId = null;

                    // Check to see if this is an insert. i.e ServiceMetadata.Id is null or empty
                    if (string.IsNullOrEmpty(entity.ServiceMetadata.Id))
                    {
                        if (wrapper.TempIdToEntityMapping == null)
                        {
                            wrapper.TempIdToEntityMapping = new Dictionary <string, IOfflineEntity>();
                        }
                        tempId = Guid.NewGuid().ToString();
                        wrapper.TempIdToEntityMapping.Add(tempId, entity);
                    }

                    this._syncWriter.AddItem(entity, tempId);
                }

                if (base.SerializationFormat == SerializationFormat.ODataAtom)
                {
                    this._syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this._syncWriter.WriteFeed(JsonReaderWriterFactory.CreateJsonWriter(requestStream));
                }

                requestStream.Flush();
                requestStream.Close();

                if (this._beforeRequestHandler != null)
                {
                    // Invoke user code and wait for them to call back us when they are done with the input request
                    this._workerManager.PostProgress(wrapper.WorkerRequest, this.FirePreRequestHandler, wrapper);
                }
                else
                {
                    this.GetWebResponse(wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #29
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream. Deserializes the response feed to
        /// retrieve the list of IOfflineEntity objects and constructs an ChangeSet for that.
        /// </summary>
        /// <param name="asyncResult">IAsyncResult object</param>
        async Task OnDownloadGetResponseCompleted(Task<WebResponse> task, AsyncArgsWrapper wrapper)
        {
            wrapper.DownloadResponse = new ChangeSet();

            HttpWebResponse response = null;
            try
            {
                try
                {
                    response = await task.ConfigureAwait(false) as HttpWebResponse;
                }
                catch (WebException we)
                {
                    wrapper.Error = we;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }
                catch (SecurityException se)
                {
                    wrapper.Error = se;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();

                    // Create the SyncReader
                    this._syncReader = (base.SerializationFormat == ClientServices.SerializationFormat.ODataAtom)
                        ? (SyncReader)new ODataAtomReader(responseStream, this._knownTypes)
                        : (SyncReader)new ODataJsonReader(responseStream, this._knownTypes);

                    // Read the response
                    while (this._syncReader.Next())
                    {
                        switch (this._syncReader.ItemType)
                        {
                            case ReaderItemType.Entry:
                                wrapper.DownloadResponse.AddItem(this._syncReader.GetItem());
                                break;
                            case ReaderItemType.SyncBlob:
                                wrapper.DownloadResponse.ServerBlob = this._syncReader.GetServerBlob();
                                break;
                            case ReaderItemType.HasMoreChanges:
                                wrapper.DownloadResponse.IsLastBatch = !this._syncReader.GetHasMoreChangesValue();
                                break;
                        }
                    }

                    wrapper.WebResponse = response;
                    // Invoke user code on the correct synchronization context.
                    this.FirePostResponseHandler(wrapper);
                }
                else
                {
                    wrapper.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                        response.StatusCode,
                        response.StatusDescription));
                }

                // If we get here then it means we completed the request. Return to the original caller
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #30
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.BeginGetResponse call
        /// </summary>
        /// <param name="task">IAsyncResult object</param>
        async Task OnUploadGetResponseCompleted(Task<WebResponse> task, AsyncArgsWrapper wrapper)
        {
            wrapper.UploadResponse = new ChangeSetResponse();

            HttpWebResponse response = null;
            try
            {
                try
                {
                    response = await task.ConfigureAwait(false) as HttpWebResponse;
                }
                catch (WebException we)
                {
                    wrapper.UploadResponse.Error = we;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }
                catch (SecurityException se)
                {
                    wrapper.UploadResponse.Error = se;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();

                    // Create the SyncReader
                    this._syncReader = (base.SerializationFormat == ClientServices.SerializationFormat.ODataAtom)
                        ? (SyncReader)new ODataAtomReader(responseStream, this._knownTypes)
                        : (SyncReader)new ODataJsonReader(responseStream, this._knownTypes);

                    // Read the response
                    while (this._syncReader.Next())
                    {
                        switch (this._syncReader.ItemType)
                        {
                            case ReaderItemType.Entry:                                
                                IOfflineEntity entity = this._syncReader.GetItem();
                                IOfflineEntity ackedEntity = entity;                                
                                string tempId = null;
                                
                                // If conflict only one temp ID should be set
                                if (this._syncReader.HasTempId() && this._syncReader.HasConflictTempId()) 
                                {
                                    throw new CacheControllerException(string.Format("Service returned a TempId '{0}' in both live and conflicting entities.", 
                                                                       this._syncReader.GetTempId()));
                                }

                                // Validate the live temp ID if any, before adding anything to the offline context
                                if (this._syncReader.HasTempId()) 
                                {
                                    tempId = this._syncReader.GetTempId();
                                    CheckEntityServiceMetadataAndTempIds(wrapper, entity, tempId);

                                }
                                           
                                //  If conflict 
                                if (this._syncReader.HasConflict()) 
                                {                                    
                                    Conflict conflict = this._syncReader.GetConflict();
                                    IOfflineEntity conflictEntity = (conflict is SyncConflict) ? 
                                                                    ((SyncConflict)conflict).LosingEntity : ((SyncError)conflict).ErrorEntity;

                                    // Validate conflict temp ID if any
                                    if (this._syncReader.HasConflictTempId())
                                    {
                                        tempId = this._syncReader.GetConflictTempId();
                                        CheckEntityServiceMetadataAndTempIds(wrapper, conflictEntity, tempId);
                                    }

                                    // Add conflict                                    
                                    wrapper.UploadResponse.AddConflict(conflict);
                                
                                    //
                                    // If there is a conflict and the tempId is set in the conflict entity then the client version lost the 
                                    // conflict and the live entity is the server version (ServerWins)
                                    //
                                    if (this._syncReader.HasConflictTempId() && entity.ServiceMetadata.IsTombstone)
                                    {
                                        //
                                        // This is a ServerWins conflict, or conflict error. The winning version is a tombstone without temp Id
                                        // so there is no way to map the winning entity with a temp Id. The temp Id is in the conflict so we are
                                        // using the conflict entity, which has the PK, to build a tombstone entity used to update the offline context
                                        //
                                        // In theory, we should copy the service metadata but it is the same end result as the service fills in
                                        // all the properties in the conflict entity
                                        //

                                        // Add the conflict entity                                              
                                        conflictEntity.ServiceMetadata.IsTombstone = true;
                                        ackedEntity = conflictEntity;
                                    }
                                }
                        
                                // Add ackedEntity to storage. If ackedEntity is still equal to entity then add non-conflict entity. 
                                if (!String.IsNullOrEmpty(tempId)) {
                                    wrapper.UploadResponse.AddUpdatedItem(ackedEntity);
                                }                                
                                break;

                            case ReaderItemType.SyncBlob:
                                wrapper.UploadResponse.ServerBlob = this._syncReader.GetServerBlob();
                                break;
                        }
                    }

                    if (wrapper.TempIdToEntityMapping != null && wrapper.TempIdToEntityMapping.Count != 0)
                    {
                        // The client sent some inserts which werent ack'd by the service. Throw.
                        StringBuilder builder = new StringBuilder("Server did not acknowledge with a permanent Id for the following tempId's: ");
                        builder.Append(string.Join(",", wrapper.TempIdToEntityMapping.Keys.ToArray()));
                        throw new CacheControllerException(builder.ToString());
                    }

                    wrapper.WebResponse = response;
                    // Invoke user code on the correct synchronization context.
                    this.FirePostResponseHandler(wrapper);
                }
                else
                {
                    wrapper.UploadResponse.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                        response.StatusCode,
                        response.StatusDescription));
                }

                // If we get here then it means we completed the request. Return to the original caller
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #31
0
 private IEnumerable<IsolatedStorageOfflineEntity> GetDownloadedValues(AsyncArgsWrapper wrapper)
 {
     while (this._syncReader.Next())
     {
         switch (_syncReader.ItemType)
         {
             case ReaderItemType.Entry:
                 IsolatedStorageOfflineEntity offlineEntity = _syncReader.GetItem();
                 var entity = offlineEntity as IEntity;
                 if (entity != null)
                     LogManager.Logger.SyncDownload(entity.EntityType, offlineEntity.ServiceMetadata.IsTombstone);
                 yield return offlineEntity;
                 break;
             case ReaderItemType.SyncBlob:
                 wrapper.DownloadResponse.ServerBlob = _syncReader.GetServerBlob();
                 break;
             case ReaderItemType.HasMoreChanges:
                 wrapper.DownloadResponse.IsLastBatch = !_syncReader.GetHasMoreChangesValue();
                 break;
         }
     }
     _syncReader.Dispose();
 }
コード例 #32
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream
        /// </summary>
        /// <param name="task">Task representing the future request stream</param>
        async Task OnDownloadGetRequestStreamCompleted(Task<Stream> task, AsyncArgsWrapper wrapper)
        {
            try
            {
                Stream requestStream = await task.ConfigureAwait(false);

                // Create a SyncWriter to write the contents
                this._syncWriter = (base.SerializationFormat == SerializationFormat.ODataAtom)
                    ? (SyncWriter)new ODataAtomWriter(base.BaseUri)
                    : (SyncWriter)new ODataJsonWriter(base.BaseUri);

                this._syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                if (base.SerializationFormat == SerializationFormat.ODataAtom)
                {
                    this._syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this._syncWriter.WriteFeed(JsonReaderWriterFactory.CreateJsonWriter(requestStream));
                }

                requestStream.Flush();
                requestStream.Close();

                if (this._beforeRequestHandler != null)
                {
                    // Invoke user code and wait for them to call back us when they are done with the input request
                    this._workerManager.PostProgress(wrapper.WorkerRequest, this.FirePreRequestHandler, wrapper);
                }
                else
                {
                    this.GetWebResponse(wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #33
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.beginGetRequestStream
        /// </summary>
        /// <param name="asyncResult">IAsyncResult object</param>
        void OnUploadGetRequestStreamCompleted(IAsyncResult asyncResult)
        {
            AsyncArgsWrapper wrapper = asyncResult.AsyncState as AsyncArgsWrapper;

            try
            {
                Stream requestStream = wrapper.WebRequest.EndGetRequestStream(asyncResult);

                // CreateInstance a SyncWriter to write the contents

                if (ApplicationContext.Current.Settings.BitMobileFormatterDisabled)
                {
                    _syncWriter = new ODataAtomWriter(BaseUri);
                }
                else
                {
                    _syncWriter = new BMWriter(BaseUri);
                }

                this._syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                foreach (IOfflineEntity entity in wrapper.CacheRequest.Changes)
                {
                    var ientity = entity as IEntity;

                    // Skip tombstones that dont have a ID element.
                    if (entity.ServiceMetadata.IsTombstone && string.IsNullOrEmpty(entity.ServiceMetadata.Id))
                    {
                        if (ientity != null)
                        {
                            LogManager.Logger.SyncUpload(ientity.EntityType, true);
                        }
                        continue;
                    }

                    string tempId = null;

                    // Check to see if this is an insert. i.e ServiceMetadata.Id is null or empty
                    if (string.IsNullOrEmpty(entity.ServiceMetadata.Id))
                    {
                        if (wrapper.TempIdToEntityMapping == null)
                        {
                            wrapper.TempIdToEntityMapping = new Dictionary <string, IOfflineEntity>();
                        }
                        tempId = Guid.NewGuid().ToString();
                        wrapper.TempIdToEntityMapping.Add(tempId, entity);
                    }

                    this._syncWriter.AddItem(entity, tempId);

                    if (ientity != null)
                    {
                        LogManager.Logger.SyncUpload(ientity.EntityType);
                    }
                }

                if (base.SerializationFormat == SerializationFormat.ODataAtom)
                {
                    this._syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                }
                else
                {
                    this._syncWriter.WriteFeed(JsonReaderWriterFactory.CreateJsonWriter(requestStream));
                }

                requestStream.Flush();
                requestStream.Close();

                if (this._beforeRequestHandler != null)
                {
                    // Invoke user code and wait for them to call back us when they are done with the input request
                    this._workerManager.PostProgress(wrapper.WorkerRequest, this.FirePreRequestHandler, wrapper);
                }
                else
                {
                    this.GetWebResponse(wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #34
0
 /// <summary>
 /// Invokes the user's AfterReceivingResponse callback.
 /// </summary>
 /// <param name="wrapper">AsyncArgsWrapper object</param>
 void FirePostResponseHandler(AsyncArgsWrapper wrapper)
 {
     if (this._afterResponseHandler != null)
     {
         // Invoke the user code.
         this._afterResponseHandler(wrapper.WebResponse);
     }
 }
コード例 #35
0
        /// <summary>
        /// Actual worker performing the work
        /// </summary>
        /// <param name="worker">AsyncWorkRequest object</param>
        /// <param name="inputParams">input parameters</param>
        void ProcessCacheRequestWorker(AsyncWorkRequest worker, object[] inputParams)
        {
            Debug.Assert(inputParams.Length == 2);

            CacheRequest request = inputParams[0] as CacheRequest;
            object state = inputParams[1];

            AsyncArgsWrapper wrapper = new AsyncArgsWrapper()
            {
                UserPassedState = state,
                WorkerRequest = worker,
                CacheRequest = request
            };

            ProcessRequest(wrapper);
        }
コード例 #36
0
        /// <summary>
        /// Method that does the actual processing.
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        /// <param name="cancellationToken"> </param>
        private async Task <AsyncArgsWrapper> ProcessRequest(AsyncArgsWrapper wrapper,
                                                             CancellationToken cancellationToken)
        {
            HttpWebResponse webResponse = null;

            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                var requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                                        BaseUri,
                                        (BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                                        Uri.EscapeUriString(ScopeName),
                                        wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (var kvp in scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key),
                                            Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                    {
                        prefix = "&";
                    }
                }

                // Create the WebRequest
                HttpWebRequest webRequest;

                if (credentials != null)
                {
                    // Create the Client Http request
                    webRequest = WebRequest.CreateHttp(new Uri(requestUri.ToString()));
                    // Add credentials
                    webRequest.Credentials = credentials;
                }
                else
                {
                    // Use WebRequest.Create the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString());
                }

                // Set the method type
                webRequest.Method = "POST";
                webRequest.Accept = (SerializationFormat == SerializationFormat.ODataAtom)
                                        ? "application/atom+xml"
                                        : "application/json";
                webRequest.ContentType = (SerializationFormat == SerializationFormat.ODataAtom)
                                             ? "application/atom+xml"
                                             : "application/json";


                // Write on the stream
#if !NETFX_CORE
                using (Stream stream = await Task.Factory.FromAsync <Stream>(
                           webRequest.BeginGetRequestStream,
                           webRequest.EndGetRequestStream, null))
#else
                using (Stream stream = await webRequest.GetRequestStreamAsync())
#endif
                {
                    if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                    {
                        WriteUploadRequestStream(stream, wrapper);
                    }
                    else
                    {
                        WriteDownloadRequestStream(stream, wrapper);
                    }
                }

                // If error, return wrapper with error
                if (wrapper.Error != null)
                {
                    return(wrapper);
                }

                // Get Response
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    wrapper.UploadResponse = new ChangeSetResponse();
                }
                else
                {
                    wrapper.DownloadResponse = new ChangeSet();
                }

#if !NETFX_CORE
                webResponse = (HttpWebResponse)(await Task.Factory.FromAsync <WebResponse>(
                                                    webRequest.BeginGetResponse,
                                                    webRequest.EndGetResponse, null));
#else
                webResponse = (HttpWebResponse)(await webRequest.GetResponseAsync());
#endif

                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    await ReadUploadResponse(webResponse, wrapper);
                }
                else
                {
                    await ReadDownloadResponse(webResponse, wrapper);
                }
            }
            catch (WebException we)
            {
                if (we.Response == null)
                {
                    wrapper.Error = we;
                }
                else
                {
                    var stream = we.Response.GetResponseStream();

                    var reader = SerializationFormat == SerializationFormat.ODataAtom ?
                                 XmlReader.Create(stream) :
                                 new XmlJsonReader(stream, XmlDictionaryReaderQuotas.Max);

                    if (reader.ReadToDescendant(FormatterConstants.ErrorDescriptionElementNamePascalCasing))
                    {
                        wrapper.Error = new Exception(reader.ReadElementContentAsString());
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                return(wrapper);
            }

            return(wrapper);
        }
コード例 #37
0
        /// <summary>
        /// Issues the BeginGetResponse call for the HttpWebRequest
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        private void GetWebResponse(AsyncArgsWrapper wrapper)
        {

            var requestData = new TimeoutRequestData()
            {
                Request = wrapper.WebRequest
            };
            // Send the request and wait for the response.
            if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
            {
                lock (_timeoutSync)
                {
                    IAsyncResult resultUpload = wrapper.WebRequest.BeginGetResponse(OnUploadGetResponseCompleted, wrapper);
                    requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultUpload.AsyncWaitHandle,
                        new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                }
            }
            else
            {
                lock (_timeoutSync)
                {
                    IAsyncResult resultDownload = wrapper.WebRequest.BeginGetResponse(OnDownloadGetResponseCompleted, wrapper);
                    requestData.Handle = ThreadPool.RegisterWaitForSingleObject(resultDownload.AsyncWaitHandle,
                        new WaitOrTimerCallback(TimeOutCallback), requestData, TIMEOUT, true);
                }
            }
        }
コード例 #38
0
        /// <summary>
        /// Method that does the actual processing.
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        /// <param name="cancellationToken"> </param>
        private async Task <AsyncArgsWrapper> ProcessRequest(AsyncArgsWrapper wrapper,
                                                             CancellationToken cancellationToken)
        {
            HttpWebResponse webResponse = null;

            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                var requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                                        BaseUri,
                                        (BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                                        Uri.EscapeUriString(ScopeName),
                                        wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (var kvp in scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key),
                                            Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                    {
                        prefix = "&";
                    }
                }

                // Create the WebRequest
                HttpWebRequest webRequest;

                if (credentials != null)
                {
                    // Create the Client Http request
                    webRequest = WebRequest.CreateHttp(new Uri(requestUri.ToString()));
                    // Add credentials
                    webRequest.Credentials = credentials;
                }
                else
                {
                    // Use WebRequest.Create the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString());
                }

                // set cookies if exists
                if (CookieContainer != null)
                {
                    webRequest.CookieContainer = CookieContainer;
                }

                // Set the method type
                webRequest.Method = "POST";
                webRequest.Accept = (SerializationFormat == SerializationFormat.ODataAtom)
                                        ? "application/atom+xml"
                                        : "application/json";
                webRequest.ContentType = (SerializationFormat == SerializationFormat.ODataAtom)
                                             ? "application/atom+xml"
                                             : "application/json";
#if !WINDOWS_PHONE
                if (automaticDecompression)
                {
                    webRequest.Headers["Accept-Encoding"] = "gzip, deflated";
                }
#endif
                foreach (var kvp in customHeaders)
                {
                    webRequest.Headers[kvp.Key] = kvp.Value;
                }
                // To be sure where it could be raise an error, just mark the step
                wrapper.Step = HttpState.WriteRequest;

#if !NETFX_CORE
                using (Stream stream = await Task.Factory.FromAsync <Stream>(
                           webRequest.BeginGetRequestStream,
                           webRequest.EndGetRequestStream, null))
#else
                using (Stream stream = await webRequest.GetRequestStreamAsync())
#endif
                {
                    if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                    {
                        WriteUploadRequestStream(stream, wrapper);
                    }
                    else
                    {
                        WriteDownloadRequestStream(stream, wrapper);
                    }
                }

                // If error, return wrapper with error
                if (wrapper.Error != null)
                {
                    return(wrapper);
                }

                // Get Response
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    wrapper.UploadResponse = new ChangeSetResponse();
                }
                else
                {
                    wrapper.DownloadResponse = new ChangeSet();
                }

                wrapper.Step = HttpState.ReadResponse;

#if !NETFX_CORE
                webResponse = (HttpWebResponse)(await Task.Factory.FromAsync <WebResponse>(
                                                    webRequest.BeginGetResponse,
                                                    webRequest.EndGetResponse, null));
#else
                webResponse = (HttpWebResponse)(await webRequest.GetResponseAsync());
#endif

                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    await ReadUploadResponse(webResponse, wrapper);
                }
                else
                {
                    await ReadDownloadResponse(webResponse, wrapper);
                }

                if (webResponse != null)
                {
                    wrapper.Step = HttpState.End;
                    webResponse.Dispose();
                    webResponse = null;
                }
            }
            catch (WebException we)
            {
                // if (we.Response == null)
                // {
                // default to this, there will be cases where the we.Response is != null but the content length = 0
                // e.g 413 and other server errors. e.g the else branch of reader.ReadToDescendent. By defaulting to this
                // we always capture the error rather then returning an error of null in some cases
                wrapper.Error = we;
                //}

                if (we.Response != null)
                {
                    using (var stream = GetWrappedStream(we.Response))
                    {
                        using (var reader = SerializationFormat == SerializationFormat.ODataAtom ?
                                            XmlReader.Create(stream) :
                                            new XmlJsonReader(stream, XmlDictionaryReaderQuotas.Max))
                        {
                            if (reader.ReadToDescendant(FormatterConstants.ErrorDescriptionElementNamePascalCasing))
                            {
                                wrapper.Error = new Exception(reader.ReadElementContentAsString());
                            }
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                return(wrapper);
            }

            return(wrapper);
        }
コード例 #39
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.BeginGetResponse call
        /// </summary>
        /// <param name="asyncResult">IAsyncResult object</param>
        void OnUploadGetResponseCompleted(IAsyncResult asyncResult)
        {
            AsyncArgsWrapper wrapper = asyncResult.AsyncState as AsyncArgsWrapper;

            wrapper.UploadResponse = new ChangeSetResponse();

            HttpWebResponse response = null;

            try
            {
                try
                {
                    response = wrapper.WebRequest.EndGetResponse(asyncResult) as HttpWebResponse;
                }
                catch (WebException we)
                {
                    wrapper.UploadResponse.Error = we;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }
                catch (SecurityException se)
                {
                    wrapper.UploadResponse.Error = se;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();

                    // CreateInstance the SyncReader
                    if (ApplicationContext.Current.Settings.BitMobileFormatterDisabled)
                    {
                        _syncReader = new ODataAtomReader(responseStream, _knownTypes);
                    }
                    else
                    {
                        _syncReader = new BMReader(responseStream, _knownTypes);
                    }

                    // Read the response
                    while (this._syncReader.Next())
                    {
                        switch (this._syncReader.ItemType)
                        {
                        case ReaderItemType.Entry:
                            IOfflineEntity entity      = this._syncReader.GetItem();
                            IOfflineEntity ackedEntity = entity;
                            string         tempId      = null;

                            // If conflict only one temp ID should be set
                            if (this._syncReader.HasTempId() && this._syncReader.HasConflictTempId())
                            {
                                throw new CacheControllerException(string.Format("Service returned a TempId '{0}' in both live and conflicting entities.",
                                                                                 this._syncReader.GetTempId()));
                            }

                            // Validate the live temp ID if any, before adding anything to the offline context
                            if (this._syncReader.HasTempId())
                            {
                                tempId = this._syncReader.GetTempId();
                                CheckEntityServiceMetadataAndTempIds(wrapper, entity, tempId);
                            }

                            //  If conflict
                            if (this._syncReader.HasConflict())
                            {
                                Conflict       conflict       = this._syncReader.GetConflict();
                                IOfflineEntity conflictEntity = (conflict is SyncConflict) ?
                                                                ((SyncConflict)conflict).LosingEntity : ((SyncError)conflict).ErrorEntity;

                                // Validate conflict temp ID if any
                                if (this._syncReader.HasConflictTempId())
                                {
                                    tempId = this._syncReader.GetConflictTempId();
                                    CheckEntityServiceMetadataAndTempIds(wrapper, conflictEntity, tempId);
                                }

                                // Add conflict
                                wrapper.UploadResponse.AddConflict(conflict);

                                //
                                // If there is a conflict and the tempId is set in the conflict entity then the client version lost the
                                // conflict and the live entity is the server version (ServerWins)
                                //
                                if (this._syncReader.HasConflictTempId() && entity.ServiceMetadata.IsTombstone)
                                {
                                    //
                                    // This is a ServerWins conflict, or conflict error. The winning version is a tombstone without temp Id
                                    // so there is no way to map the winning entity with a temp Id. The temp Id is in the conflict so we are
                                    // using the conflict entity, which has the PK, to build a tombstone entity used to update the offline context
                                    //
                                    // In theory, we should copy the service metadata but it is the same end result as the service fills in
                                    // all the properties in the conflict entity
                                    //

                                    // Add the conflict entity
                                    conflictEntity.ServiceMetadata.IsTombstone = true;
                                    ackedEntity = conflictEntity;
                                }
                            }

                            // Add ackedEntity to storage. If ackedEntity is still equal to entity then add non-conflict entity.
                            if (!String.IsNullOrEmpty(tempId))
                            {
                                wrapper.UploadResponse.AddUpdatedItem(ackedEntity);
                            }
                            break;

                        case ReaderItemType.SyncBlob:
                            wrapper.UploadResponse.ServerBlob = this._syncReader.GetServerBlob();
                            break;
                        }
                    }

                    wrapper.WebResponse = response;
                    // Invoke user code on the correct synchronization context.
                    this.FirePostResponseHandler(wrapper);
                }
                else
                {
                    wrapper.UploadResponse.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }

                // If we get here then it means we completed the request. Return to the original caller
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #40
0
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream
        /// </summary>
        private void WriteDownloadRequestStream(Stream requestStream, AsyncArgsWrapper wrapper)
        {
            try
            {
                // Create a SyncWriter to write the contents
                var syncWriter = (SerializationFormat == SerializationFormat.ODataAtom)
                    ? new ODataAtomWriter(BaseUri)
                    : (SyncWriter)new ODataJsonWriter(BaseUri);

                //syncWriter = new ODataAtomWriter(BaseUri);

                syncWriter.StartFeed(wrapper.CacheRequest.IsLastBatch, wrapper.CacheRequest.KnowledgeBlob ?? new byte[0]);

                if (SerializationFormat == SerializationFormat.ODataAtom)
                    syncWriter.WriteFeed(XmlWriter.Create(requestStream));
                else
                    syncWriter.WriteFeed(new XmlJsonWriter(requestStream));

                requestStream.Flush();
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                    throw;

                wrapper.Error = e;
            }
        }
コード例 #41
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.BeginGetResponse call
        /// </summary>
        /// <param name="task">IAsyncResult object</param>
        async Task OnUploadGetResponseCompleted(Task <WebResponse> task, AsyncArgsWrapper wrapper)
        {
            wrapper.UploadResponse = new ChangeSetResponse();

            HttpWebResponse response = null;

            try
            {
                try
                {
                    response = await task.ConfigureAwait(false) as HttpWebResponse;
                }
                catch (WebException we)
                {
                    wrapper.UploadResponse.Error = we;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }
                catch (SecurityException se)
                {
                    wrapper.UploadResponse.Error = se;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();

                    // Create the SyncReader
                    this._syncReader = (base.SerializationFormat == ClientServices.SerializationFormat.ODataAtom)
                        ? (SyncReader) new ODataAtomReader(responseStream, this._knownTypes)
                        : (SyncReader) new ODataJsonReader(responseStream, this._knownTypes);

                    // Read the response
                    while (this._syncReader.Next())
                    {
                        switch (this._syncReader.ItemType)
                        {
                        case ReaderItemType.Entry:
                            IOfflineEntity entity      = this._syncReader.GetItem();
                            IOfflineEntity ackedEntity = entity;
                            string         tempId      = null;

                            // If conflict only one temp ID should be set
                            if (this._syncReader.HasTempId() && this._syncReader.HasConflictTempId())
                            {
                                throw new CacheControllerException(string.Format("Service returned a TempId '{0}' in both live and conflicting entities.",
                                                                                 this._syncReader.GetTempId()));
                            }

                            // Validate the live temp ID if any, before adding anything to the offline context
                            if (this._syncReader.HasTempId())
                            {
                                tempId = this._syncReader.GetTempId();
                                CheckEntityServiceMetadataAndTempIds(wrapper, entity, tempId);
                            }

                            //  If conflict
                            if (this._syncReader.HasConflict())
                            {
                                Conflict       conflict       = this._syncReader.GetConflict();
                                IOfflineEntity conflictEntity = (conflict is SyncConflict) ?
                                                                ((SyncConflict)conflict).LosingEntity : ((SyncError)conflict).ErrorEntity;

                                // Validate conflict temp ID if any
                                if (this._syncReader.HasConflictTempId())
                                {
                                    tempId = this._syncReader.GetConflictTempId();
                                    CheckEntityServiceMetadataAndTempIds(wrapper, conflictEntity, tempId);
                                }

                                // Add conflict
                                wrapper.UploadResponse.AddConflict(conflict);

                                //
                                // If there is a conflict and the tempId is set in the conflict entity then the client version lost the
                                // conflict and the live entity is the server version (ServerWins)
                                //
                                if (this._syncReader.HasConflictTempId() && entity.ServiceMetadata.IsTombstone)
                                {
                                    //
                                    // This is a ServerWins conflict, or conflict error. The winning version is a tombstone without temp Id
                                    // so there is no way to map the winning entity with a temp Id. The temp Id is in the conflict so we are
                                    // using the conflict entity, which has the PK, to build a tombstone entity used to update the offline context
                                    //
                                    // In theory, we should copy the service metadata but it is the same end result as the service fills in
                                    // all the properties in the conflict entity
                                    //

                                    // Add the conflict entity
                                    conflictEntity.ServiceMetadata.IsTombstone = true;
                                    ackedEntity = conflictEntity;
                                }
                            }

                            // Add ackedEntity to storage. If ackedEntity is still equal to entity then add non-conflict entity.
                            if (!String.IsNullOrEmpty(tempId))
                            {
                                wrapper.UploadResponse.AddUpdatedItem(ackedEntity);
                            }
                            break;

                        case ReaderItemType.SyncBlob:
                            wrapper.UploadResponse.ServerBlob = this._syncReader.GetServerBlob();
                            break;
                        }
                    }

                    if (wrapper.TempIdToEntityMapping != null && wrapper.TempIdToEntityMapping.Count != 0)
                    {
                        // The client sent some inserts which werent ack'd by the service. Throw.
                        StringBuilder builder = new StringBuilder("Server did not acknowledge with a permanent Id for the following tempId's: ");
                        builder.Append(string.Join(",", wrapper.TempIdToEntityMapping.Keys.ToArray()));
                        throw new CacheControllerException(builder.ToString());
                    }

                    wrapper.WebResponse = response;
                    // Invoke user code on the correct synchronization context.
                    this.FirePostResponseHandler(wrapper);
                }
                else
                {
                    wrapper.UploadResponse.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }

                // If we get here then it means we completed the request. Return to the original caller
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #42
0
        /// <summary>
        /// Callback for the Upload HttpWebRequest.BeginGetResponse call
        /// </summary>
        private async Task ReadUploadResponse(HttpWebResponse response, AsyncArgsWrapper wrapper)
        {
            try
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    using (Stream responseStream = GetWrappedStream(response))
                    {

                        using (var syncReader = (SerializationFormat == SerializationFormat.ODataAtom)
                            ? new ODataAtomReader(responseStream, this.knownTypes)
                            : (SyncReader)new ODataJsonReader(responseStream, this.knownTypes))
                        {

                            // Read the response
                            await Task.Factory.StartNew(() =>
                            {
                                while (syncReader.Next())
                                {
                                    switch (syncReader.ItemType)
                                    {
                                        case ReaderItemType.Entry:
                                            IOfflineEntity entity = syncReader.GetItem();
                                            IOfflineEntity ackedEntity = entity;
                                            string tempId = null;

                                            // If conflict only one temp ID should be set
                                            if (syncReader.HasTempId() && syncReader.HasConflictTempId())
                                            {
                                                throw new CacheControllerException(
                                                    string.Format(
                                                        "Service returned a TempId '{0}' in both live and conflicting entities.",
                                                        syncReader.GetTempId()));
                                            }

                                            // Validate the live temp ID if any, before adding anything to the offline context
                                            if (syncReader.HasTempId())
                                            {
                                                tempId = syncReader.GetTempId();
                                                CheckEntityServiceMetadataAndTempIds(wrapper, entity, tempId);
                                            }

                                            //  If conflict 
                                            if (syncReader.HasConflict())
                                            {
                                                Conflict conflict = syncReader.GetConflict();
                                                IOfflineEntity conflictEntity = (conflict is SyncConflict)
                                                                                    ? ((SyncConflict)conflict).LosingEntity
                                                                                    : ((SyncError)conflict).ErrorEntity;

                                                // Validate conflict temp ID if any
                                                if (syncReader.HasConflictTempId())
                                                {
                                                    tempId = syncReader.GetConflictTempId();
                                                    CheckEntityServiceMetadataAndTempIds(wrapper, conflictEntity, tempId);
                                                }

                                                // Add conflict                                    
                                                wrapper.UploadResponse.AddConflict(conflict);

                                                //
                                                // If there is a conflict and the tempId is set in the conflict entity then the client version lost the 
                                                // conflict and the live entity is the server version (ServerWins)
                                                //
                                                if (syncReader.HasConflictTempId() && entity.GetServiceMetadata().IsTombstone)
                                                {
                                                    //
                                                    // This is a ServerWins conflict, or conflict error. The winning version is a tombstone without temp Id
                                                    // so there is no way to map the winning entity with a temp Id. The temp Id is in the conflict so we are
                                                    // using the conflict entity, which has the PK, to build a tombstone entity used to update the offline context
                                                    //
                                                    // In theory, we should copy the service metadata but it is the same end result as the service fills in
                                                    // all the properties in the conflict entity
                                                    //

                                                    // Add the conflict entity                                              
                                                    conflictEntity.GetServiceMetadata().IsTombstone = true;
                                                    ackedEntity = conflictEntity;
                                                }
                                            }

                                            // Add ackedEntity to storage. If ackedEntity is still equal to entity then add non-conflict entity. 
                                            if (!String.IsNullOrEmpty(tempId))
                                            {
                                                wrapper.UploadResponse.AddUpdatedItem(ackedEntity);
                                            }
                                            break;

                                        case ReaderItemType.SyncBlob:
                                            wrapper.UploadResponse.ServerBlob = syncReader.GetServerBlob();
                                            break;
                                    }
                                }
                            });


                            if (wrapper.TempIdToEntityMapping != null && wrapper.TempIdToEntityMapping.Count != 0)
                            {
                                // The client sent some inserts which werent ack'd by the service. Throw.
                                var builder =
                                    new StringBuilder(
                                        "Server did not acknowledge with a permanent Id for the following tempId's: ");
                                builder.Append(string.Join(",", wrapper.TempIdToEntityMapping.Keys.ToArray()));
                                throw new CacheControllerException(builder.ToString());
                            }
                        }
                    }
                }
                else
                {
                    wrapper.UploadResponse.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                    throw;

                wrapper.Error = e;
            }
        }
コード例 #43
0
        private void CheckEntityServiceMetadataAndTempIds(AsyncArgsWrapper wrapper, IOfflineEntity entity, string tempId)
        {
            // Check service ID
            if (string.IsNullOrEmpty(entity.ServiceMetadata.Id))
            {
                throw new CacheControllerException(string.Format("Service did not return a permanent Id for tempId '{0}'", tempId));
            }

            // If an entity has a temp id then it should not be a tombstone
            if (entity.ServiceMetadata.IsTombstone) {
                throw new CacheControllerException(string.Format("Service returned a tempId '{0}' in tombstoned entity.", tempId));
            }

            // Check that the tempId was sent by client
            if (!wrapper.TempIdToEntityMapping.ContainsKey(tempId))
            {
                throw new CacheControllerException("Service returned a response for a tempId which was not uploaded by the client. TempId: " + tempId);
            }

            // Once received, remove the tempId from the mapping list.
            wrapper.TempIdToEntityMapping.Remove(tempId);
        }
        /// <summary>
        /// Method that does the actual processing.
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        void ProcessRequest(AsyncArgsWrapper wrapper)
        {
            try
            {
                StringBuilder requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                                        base.BaseUri,
                                        (base.BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                                        Uri.EscapeUriString(base.ScopeName),
                                        wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (KeyValuePair <string, string> kvp in this._scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key), Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                    {
                        prefix = "&";
                    }
                }

                // Create the WebRequest
                HttpWebRequest webRequest = null;

                if (this._credentials != null)
                {
                    // Create the Client Http request
                    webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(requestUri.ToString()));
                    // Add credentials
                    webRequest.Credentials = this._credentials;
                }
                else
                {
                    // Use WebRequest.Create the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString());
                }

                // Set the method type
                webRequest.Method      = "POST";
                webRequest.Accept      = (base.SerializationFormat == SerializationFormat.ODataAtom) ? "application/atom+xml" : "application/json";
                webRequest.ContentType = (base.SerializationFormat == SerializationFormat.ODataAtom) ? "application/atom+xml" : "application/json";

                wrapper.WebRequest = webRequest;

                // Get the request stream
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    webRequest.BeginGetRequestStream(OnUploadGetRequestStreamCompleted, wrapper);
                }
                else
                {
                    webRequest.BeginGetRequestStream(OnDownloadGetRequestStreamCompleted, wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #45
0
 /// <summary>
 /// Issues the BeginGetResponse call for the HttpWebRequest
 /// </summary>
 /// <param name="wrapper">AsyncArgsWrapper object</param>
 private void GetWebResponse(AsyncArgsWrapper wrapper)
 {
     // Send the request and wait for the response.
     if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
     {
         wrapper.WebRequest.BeginGetResponse(OnUploadGetResponseCompleted, wrapper);
     }
     else
     {
         wrapper.WebRequest.BeginGetResponse(OnDownloadGetResponseCompleted, wrapper);
     }
 }
        /// <summary>
        /// Callback for the Download HttpWebRequest.beginGetRequestStream. Deserializes the response feed to
        /// retrieve the list of IOfflineEntity objects and constructs an ChangeSet for that.
        /// </summary>
        /// <param name="asyncResult">IAsyncResult object</param>
        void OnDownloadGetResponseCompleted(IAsyncResult asyncResult)
        {
            AsyncArgsWrapper wrapper = asyncResult.AsyncState as AsyncArgsWrapper;

            wrapper.DownloadResponse = new ChangeSet();

            HttpWebResponse response = null;

            try
            {
                try
                {
                    response = wrapper.WebRequest.EndGetResponse(asyncResult) as HttpWebResponse;
                }
                catch (WebException we)
                {
                    wrapper.Error = we;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }
                catch (SecurityException se)
                {
                    wrapper.Error = se;
                    // If we get here then it means we completed the request. Return to the original caller
                    this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
                    return;
                }

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();

                    // Create the SyncReader
                    this._syncReader = (base.SerializationFormat == ClientServices.SerializationFormat.ODataAtom)
                        ? (SyncReader) new ODataAtomReader(responseStream, this._knownTypes)
                        : (SyncReader) new ODataJsonReader(responseStream, this._knownTypes);

                    // Read the response
                    while (this._syncReader.Next())
                    {
                        switch (this._syncReader.ItemType)
                        {
                        case ReaderItemType.Entry:
                            wrapper.DownloadResponse.AddItem(this._syncReader.GetItem());
                            break;

                        case ReaderItemType.SyncBlob:
                            wrapper.DownloadResponse.ServerBlob = this._syncReader.GetServerBlob();
                            break;

                        case ReaderItemType.HasMoreChanges:
                            wrapper.DownloadResponse.IsLastBatch = !this._syncReader.GetHasMoreChangesValue();
                            break;
                        }
                    }

                    wrapper.WebResponse = response;
                    // Invoke user code on the correct synchronization context.
                    this.FirePostResponseHandler(wrapper);
                }
                else
                {
                    wrapper.Error = new CacheControllerException(
                        string.Format("Remote service returned error status. Status: {0}, Description: {1}",
                                      response.StatusCode,
                                      response.StatusDescription));
                }

                // If we get here then it means we completed the request. Return to the original caller
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #47
0
        /// <summary>
        /// Method that does the actual processing. 
        /// 1. It first creates an HttpWebRequest
        /// 2. Fills in the required method type and parameters.
        /// 3. Attaches the user specified ICredentials.
        /// 4. Serializes the input params (Server blob for downloads and input feed for uploads)
        /// 5. If user has specified an BeforeSendingRequest callback then invokes it
        /// 6. Else proceeds to issue the request
        /// </summary>
        /// <param name="wrapper">AsyncArgsWrapper object</param>
        void ProcessRequest(AsyncArgsWrapper wrapper)
        {
            try
            {
                StringBuilder requestUri = new StringBuilder();
                requestUri.AppendFormat("{0}{1}{2}/{3}",
                    base.BaseUri,
                    (base.BaseUri.ToString().EndsWith("/")) ? string.Empty : "/",
                    Uri.EscapeUriString(base.ScopeName),
                    wrapper.CacheRequest.RequestType.ToString());

                string prefix = "?";
                // Add the scope params if any
                foreach (KeyValuePair<string, string> kvp in this._scopeParameters)
                {
                    requestUri.AppendFormat("{0}{1}={2}", prefix, Uri.EscapeUriString(kvp.Key), Uri.EscapeUriString(kvp.Value));
                    if (prefix.Equals("?"))
                    {
                        prefix = "&";
                    }
                }

                // Create the WebRequest
                HttpWebRequest webRequest = null;

                if (this._credentials != null)
                {
                    // Create the Client Http request
                    webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(requestUri.ToString()));
                    // Add credentials
                    webRequest.Credentials = this._credentials;
                }
                else
                {
                    // Use WebRequest.Create the request. This uses any user defined prefix preferences for certain paths
                    webRequest = (HttpWebRequest)WebRequest.Create(requestUri.ToString());
                }

                // Set the method type
                webRequest.Method = "POST";
                webRequest.Accept = (base.SerializationFormat == SerializationFormat.ODataAtom) ? "application/atom+xml" : "application/json";
                webRequest.ContentType = (base.SerializationFormat == SerializationFormat.ODataAtom) ? "application/atom+xml" : "application/json";

                wrapper.WebRequest = webRequest;

                // Get the request stream
                if (wrapper.CacheRequest.RequestType == CacheRequestType.UploadChanges)
                {
                    webRequest.BeginGetRequestStream(OnUploadGetRequestStreamCompleted, wrapper);
                }
                else
                {
                    webRequest.BeginGetRequestStream(OnDownloadGetRequestStreamCompleted, wrapper);
                }
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }
                wrapper.Error = e;
                this._workerManager.CompleteWorkRequest(wrapper.WorkerRequest, wrapper);
            }
        }
コード例 #48
0
        void ProcessCacheRequestWorker(AsyncWorkRequest worker, object[] inputParams)
        {
            var request = inputParams[0] as CacheRequest;
            object state = inputParams[1];

            _wrapper = new AsyncArgsWrapper
            {
                UserPassedState = state,
                WorkerRequest = worker,
                CacheRequest = request
            };

            ProcessRequest();
        }