/// <summary> /// inserts the entry asynchronous, you need to supply a valid and unique /// token. Events will be send to the async delegates you setup on the service /// object /// </summary> /// <param name="feedUri">the target feed the entry get's inserted into</param> /// <param name="entry"></param> /// <param name="userData">a unique identifier to associate this request with</param> /// <returns></returns> public void InsertAsync(Uri feedUri, AtomEntry entry, Object userData) { AsyncSendData data = new AsyncSendData(this, feedUri, entry, ProgressReportDelegate, userData); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncInsertWorker); AsyncStarter(data, workerDelegate, userData); }
/// <summary> /// takes a given feed, and does a batch post of that feed /// against the batchUri parameter. If that one is NULL /// it will try to use the batch link URI in the feed /// </summary> /// <param name="feed">the feed to post</param> /// <param name="batchUri">the URI to user</param> /// <param name="userData">the userdata identifying this request</param> /// <returns></returns> public void BatchAsync(AtomFeed feed, Uri batchUri, Object userData) { AsyncSendData data = new AsyncSendData(this, batchUri, feed, ProgressReportDelegate, userData); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncBatchWorker); AsyncStarter(data, workerDelegate, userData); }
/// <summary> /// takes a given feed, and does a batch post of that feed /// against the batchUri parameter. If that one is NULL /// it will try to use the batch link URI in the feed /// </summary> /// <param name="feed">the feed to post</param> /// <param name="batchUri">the URI to user</param> /// <param name="data">The async data payload</param> /// <returns>the returned AtomFeed</returns> private AtomFeed Batch(AtomFeed feed, Uri batchUri, AsyncSendData data) { Uri uriToUse = batchUri; if (feed == null) { throw new ArgumentNullException("feed"); } if (uriToUse == null) { uriToUse = feed.Batch == null ? null : new Uri(feed.Batch); } if (uriToUse == null) { throw new ArgumentNullException("batchUri"); } Tracing.Assert(feed != null, "feed should not be null"); if (feed == null) { throw new ArgumentNullException("feed"); } if (feed.BatchData == null) { // setting this will make the feed output the namespace, instead of each entry feed.BatchData = new GDataBatchFeedData(); } Stream returnStream = EntrySend(uriToUse, feed, GDataRequestType.Batch, data); return(CreateAndParseFeed(returnStream, uriToUse)); }
/// <summary> /// updates the entry asynchronous, you need to supply a valid and unique /// token. Events will be send to the async delegates you setup on the service /// object /// </summary> /// <param name="entry"></param> /// <param name="userData">a unique identifier to associate this request with</param> /// <returns></returns> public void UpdateAsync(AtomEntry entry, Object userData) { AsyncSendData data = new AsyncSendData(this, entry, ProgressReportDelegate, userData); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncUpdateWorker); AsyncStarter(data, workerDelegate, userData); }
/// <summary> /// this is a helper function for to send binary data asyncronous to a resource /// </summary> /// <param name="targetUri"></param> /// <param name="inputStream"></param> /// <param name="type"></param> /// <param name="contentType">the contenttype to use in the request, if NULL is passed, factory default is used</param> /// <param name="slugHeader">the slugHeader to use in the request, if NULL is passed, factory default is used</param> /// <param name="userData">a unique identifier to associate this request with</param> /// <param name="parseFeed">indicates if the async operation should try to parse the server returned stream, or just return the stream</param> /// <returns></returns> private void StreamSendAsync( Uri targetUri, Stream inputStream, GDataRequestType type, string contentType, string slugHeader, object userData, bool parseFeed) { AsyncSendData data = new AsyncSendData(this, targetUri, inputStream, type, contentType, slugHeader, ProgressReportDelegate, userData, parseFeed); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncStreamSendWorker); AsyncStarter(data, workerDelegate, userData); }
/// <summary> /// starts the async job /// </summary> /// <param name="data"></param> /// <param name="userData"></param> /// <param name="workerDelegate"></param> /// <returns></returns> private void AsyncStarter(AsyncSendData data, WorkerSendEventHandler workerDelegate, Object userData) { AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userData); data.Operation = asyncOp; AddUserDataToDictionary(userData, asyncOp); // Start the asynchronous operation. workerDelegate.BeginInvoke( data, asyncOp, CompletionMethodDelegate, null, null); }
/// <summary> /// worker method for the direct stream send /// </summary> /// <param name="data"></param> /// <param name="asyncOp"></param> /// <param name="completionMethodDelegate"></param> /// <returns></returns> private void AsyncStreamSendWorker(AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) { try { using (var responseStream = StreamSend(data.UriToUse, data.DataStream, data.Type, data.ContentType, data.SlugHeader, null, data)) { HandleResponseStream(data, responseStream, -1); } } catch (Exception e) { data.Exception = e; } completionMethodDelegate(data); }
/// <summary> /// worker method for the batch case /// </summary> /// <param name="data"></param> /// <param name="asyncOp"></param> /// <param name="completionMethodDelegate"></param> /// <returns></returns> private void AsyncBatchWorker( AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) { try { data.Feed = Batch(data.Feed, data.UriToUse, data); } catch (Exception e) { data.Exception = e; } completionMethodDelegate(data); }
/// <summary> /// worker method for the update case /// </summary> /// <param name="data"></param> /// <param name="asyncOp"></param> /// <param name="completionMethodDelegate"></param> /// <returns></returns> private void AsyncUpdateWorker( AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) { try { data.Entry = Update(data.Entry, data); } catch (Exception e) { data.Exception = e; } completionMethodDelegate(data); }
/// <summary>WebResponse Update(Uri updateUri, Stream entryStream, ICredentials credentials)</summary> /// <param name="entry">the old entry to update</param> /// <param name="data">the async data block used</param> /// <returns> the new Entry, as returned from the server</returns> private AtomEntry Update(AtomEntry entry, AsyncSendData data) { Tracing.Assert(entry != null, "entry should not be null"); if (entry == null) { throw new ArgumentNullException("entry"); } if (entry.ReadOnly) { throw new GDataRequestException("Can not update a read-only entry"); } Uri target = new Uri(entry.EditUri.ToString()); Stream returnStream = EntrySend(target, entry, GDataRequestType.Update, data); return(CreateAndParseEntry(returnStream, target)); }
/// <summary>public WebResponse Insert(Uri insertUri, Stream entryStream, ICredentials credentials)</summary> /// <param name="feedUri">the uri for the feed this entry should be inserted into</param> /// <param name="newEntry">the entry to be inserted</param> /// <param name="data">the data used for an async request</param> /// <returns> the inserted entry</returns> private AtomEntry Insert(Uri feedUri, AtomEntry newEntry, AsyncSendData data) { Tracing.Assert(feedUri != null, "feedUri should not be null"); if (feedUri == null) { throw new ArgumentNullException("feedUri"); } Tracing.Assert(newEntry != null, "newEntry should not be null"); if (newEntry == null) { throw new ArgumentNullException("newEntry"); } _versionInfo.ImprintVersion(newEntry); Stream returnStream = EntrySend(feedUri, newEntry, GDataRequestType.Insert, data); return(CreateAndParseEntry(returnStream, feedUri)); }
///////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// /// <summary>Inserts an AtomBase entry against a Uri. The overloaded /// version here will check if this is an AbstractEntry and if it has /// a media property set. If so, it will create a mime multipart envelope</summary> /// <param name="feedUri">the uri for the feed this object should be posted against</param> /// <param name="baseEntry">the entry to be inserted</param> /// <param name="type">the type of request to create</param> /// <param name="data">the async data payload</param> /// <returns> the response as a stream</returns> ////////////////////////////////////////////////////////////////////// internal override Stream EntrySend(Uri feedUri, AtomBase baseEntry, GDataRequestType type, AsyncSendData data) { if (feedUri == null) { throw new ArgumentNullException("feedUri"); } Tracing.Assert(baseEntry != null, "baseEntry should not be null"); if (baseEntry == null) { throw new ArgumentNullException("baseEntry"); } AbstractEntry entry = baseEntry as AbstractEntry; // if the entry is not an abstractentry or if no media is set, do the default if (entry == null || entry.MediaSource == null) { return(base.EntrySend(feedUri, baseEntry, type, data)); } Stream outputStream = null; Stream inputStream = null; try { IGDataRequest request = RequestFactory.CreateRequest(type, feedUri); request.Credentials = Credentials; GDataRequest r = request as GDataRequest; if (r != null) { r.ContentType = MediaService.MimeContentType; r.Slug = entry.MediaSource.Name; GDataRequestFactory f = RequestFactory as GDataRequestFactory; if (f != null) { f.CustomHeaders.Add("MIME-version: 1.0"); } } if (data != null) { GDataGAuthRequest gr = request as GDataGAuthRequest; if (gr != null) { gr.AsyncData = data; } } outputStream = request.GetRequestStream(); inputStream = entry.MediaSource.GetDataStream(); StreamWriter w = new StreamWriter(outputStream); w.WriteLine("Media multipart posting"); CreateBoundary(w, GDataRequestFactory.DefaultContentType); baseEntry.SaveToXml(outputStream); w.WriteLine(); CreateBoundary(w, entry.MediaSource.ContentType); WriteInputStreamToRequest(inputStream, outputStream); w.WriteLine(); w.WriteLine("--" + MediaService.MimeBoundary + "--"); w.Flush(); request.Execute(); outputStream.Close(); outputStream = null; return(request.GetResponseStream()); } catch (Exception) { throw; } finally { if (outputStream != null) { outputStream.Close(); } if (inputStream != null) { inputStream.Close(); } } }
/// <summary> /// this is a helper function for to send binary data to a resource /// it is not worth running the other insert/saves through here, as this would involve /// double buffering/copying of the bytes /// </summary> /// <param name="targetUri"></param> /// <param name="inputStream"></param> /// <param name="type"></param> /// <param name="contentType">the contenttype to use in the request, if NULL is passed, factory default is used</param> /// <param name="slugHeader">the slugHeader to use in the request, if NULL is passed, factory default is used</param> /// <param name="etag">The http etag to pass into the request</param> /// <param name="data">The async data needed for notifications</param> /// <returns>Stream from the server response. You should close this stream explicitly.</returns> private Stream StreamSend( Uri targetUri, Stream inputStream, GDataRequestType type, string contentType, string slugHeader, string etag, AsyncSendData data) { Tracing.Assert(targetUri != null, "targetUri should not be null"); if (targetUri == null) { throw new ArgumentNullException("targetUri"); } if (inputStream == null) { Tracing.Assert(inputStream != null, "payload should not be null"); throw new ArgumentNullException("inputStream"); } if (type != GDataRequestType.Insert && type != GDataRequestType.Update) { Tracing.Assert(type != GDataRequestType.Insert && type != GDataRequestType.Update, "type needs to be insert or update"); throw new ArgumentNullException("type"); } IGDataRequest request = RequestFactory.CreateRequest(type, targetUri); request.Credentials = Credentials; if (data != null) { GDataGAuthRequest gr = request as GDataGAuthRequest; if (gr != null) { gr.AsyncData = data; } } // set the contenttype of the request if (contentType != null) { GDataRequest r = request as GDataRequest; if (r != null) { r.ContentType = contentType; } } if (slugHeader != null) { GDataRequest r = request as GDataRequest; if (r != null) { r.Slug = slugHeader; } } if (etag != null) { ISupportsEtag ise = request as ISupportsEtag; if (ise != null) { ise.Etag = etag; } } Stream outputStream = request.GetRequestStream(); WriteInputStreamToRequest(inputStream, outputStream); request.Execute(); outputStream.Close(); return(new GDataReturnStream(request)); }
/// <summary>Inserts an AtomBase entry against a Uri</summary> /// <param name="feedUri">the uri for the feed this object should be posted against</param> /// <param name="baseEntry">the entry to be inserted</param> /// <param name="type">the type of request to create</param> /// <param name="data">the async data payload</param> /// <returns> the response as a stream</returns> internal virtual Stream EntrySend(Uri feedUri, AtomBase baseEntry, GDataRequestType type, AsyncSendData data) { Tracing.Assert(feedUri != null, "feedUri should not be null"); if (feedUri == null) { throw new ArgumentNullException("feedUri"); } Tracing.Assert(baseEntry != null, "baseEntry should not be null"); if (baseEntry == null) { throw new ArgumentNullException("baseEntry"); } _versionInfo.ImprintVersion(baseEntry); IGDataRequest request = RequestFactory.CreateRequest(type, feedUri); request.Credentials = Credentials; ISupportsEtag eTarget = request as ISupportsEtag; ISupportsEtag eSource = baseEntry as ISupportsEtag; if (eTarget != null && eSource != null) { eTarget.Etag = eSource.Etag; } request.ContentStore = baseEntry; request.IsBatch = type == GDataRequestType.Batch; if (data != null) { GDataGAuthRequest gr = request as GDataGAuthRequest; if (gr != null) { gr.AsyncData = data; } } Stream outputStream = request.GetRequestStream(); baseEntry.SaveToXml(outputStream); request.Execute(); outputStream.Close(); return(request.GetResponseStream()); }