/// <summary> /// This method is invoked by the data services framework whenever an insert or update operation is /// being processed for the stream associated with the Entity Type specified via the entity parameter. /// </summary> /// <param name="entity">The stream returned should be the default stream associated with this entity.</param> /// <param name="streamProperty">Stream info instance. If it is null, the corresponding method defined on IDataServiceStreamProvider will be invoked. /// Otherwise the corresponding method defined on IDataServiceStreamProvider2 will be called with the name of the stream.</param> /// <param name="operationContext">A reference to the context for the current operation.</param> /// <returns>A valid stream the data service use to write the contents of a BLOB which is associated with <paramref name="entity"/>.</returns> internal Stream GetWriteStream(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext) { Debug.Assert(entity != null, "entity != null"); Debug.Assert(operationContext != null, "operationContext != null"); string etag; bool? checkETagForEquality; DataServiceStreamProviderWrapper.GetETagFromHeaders(operationContext, out etag, out checkETagForEquality); Debug.Assert( string.IsNullOrEmpty(etag) && !checkETagForEquality.HasValue || !string.IsNullOrEmpty(etag) && checkETagForEquality.HasValue, "etag and checkETagForEquality parameters must both be set or not set at the same time."); Stream writeStream; if (streamProperty == null) { writeStream = InvokeApiCallAndValidateHeaders("IDataServiceStreamProvider.GetWriteStream", () => this.LoadAndValidateStreamProvider().GetWriteStream(entity, etag, checkETagForEquality, operationContext), operationContext); } else { Debug.Assert(!string.IsNullOrEmpty(streamProperty.Name), "!string.IsNullOrEmpty(stream.Name)"); writeStream = InvokeApiCallAndValidateHeaders("IDataServiceStreamProvider2.GetWriteStream", () => this.LoadAndValidateStreamProvider2().GetWriteStream(entity, streamProperty, etag, checkETagForEquality, operationContext), operationContext); } if (writeStream == null || !writeStream.CanWrite) { WebUtil.Dispose(writeStream); throw new InvalidOperationException(Strings.DataService_InvalidStreamFromGetWriteStream); } return(writeStream); }
/// <summary> /// This method is invoked by the data services framework to retrieve the default stream associated /// with the Entity Type specified by the <paramref name="entity"/> parameter. /// Note that we set the response ETag in the host object before we return. /// </summary> /// <param name="entity">The stream returned should be the default stream associated with this entity.</param> /// <param name="streamProperty">Stream property instance. If it is null, the corresponding method defined on IDataServiceStreamProvider will be invoked. /// Otherwise the corresponding method defined on IDataServiceStreamProvider2 will be called with the name of the stream.</param> /// <param name="operationContext">A reference to the context for the current operation.</param> /// <returns>A valid stream the data service use to query / read a streamed BLOB which is associated with the <paramref name="entity"/>.</returns> internal Stream GetReadStream(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext) { Debug.Assert(entity != null, "entity != null"); Debug.Assert(operationContext != null, "operationContext != null"); string etagFromHeader; bool? checkETagForEquality; DataServiceStreamProviderWrapper.GetETagFromHeaders(operationContext, out etagFromHeader, out checkETagForEquality); Debug.Assert( string.IsNullOrEmpty(etagFromHeader) && !checkETagForEquality.HasValue || !string.IsNullOrEmpty(etagFromHeader) && checkETagForEquality.HasValue, "etag and checkETagForEquality parameters must both be set or not set at the same time."); Stream readStream; try { if (streamProperty == null) { readStream = InvokeApiCallAndValidateHeaders("IDataServiceStreamProvider.GetReadStream", () => this.LoadAndValidateStreamProvider().GetReadStream(entity, etagFromHeader, checkETagForEquality, operationContext), operationContext); } else { Debug.Assert(!string.IsNullOrEmpty(streamProperty.Name), "!string.IsNullOrEmpty(stream.Name)"); readStream = InvokeApiCallAndValidateHeaders("IDataServiceStreamProvider2.GetReadStream", () => this.LoadAndValidateStreamProvider2().GetReadStream(entity, streamProperty, etagFromHeader, checkETagForEquality, operationContext), operationContext); } } catch (DataServiceException e) { if (e.StatusCode == (int)System.Net.HttpStatusCode.NotModified) { // For status code 304, we MUST set the etag value. Our Error handler will translate // DataServiceException(304) to a normal response with status code 304 and an empty message-body. WebUtil.WriteETagValueInResponseHeader(null, this.GetStreamETag(entity, streamProperty, operationContext), operationContext.ResponseMessage); } throw; } try { if (streamProperty == null) { // For default streams, we always expect GetReadStream() to return a non-null readable stream. if (readStream == null || !readStream.CanRead) { throw new InvalidOperationException(Strings.DataService_InvalidStreamFromGetReadStream); } } else { // For named streams, GetReadStream() can return null to indicate that the stream has not been created. if (readStream == null) { // 204 == no content operationContext.ResponseStatusCode = 204; } else if (!readStream.CanRead) { throw new InvalidOperationException(Strings.DataService_InvalidStreamFromGetReadStream); } } // GetStreamETag can throw and we need to catch and dispose the stream. WebUtil.WriteETagValueInResponseHeader(null, this.GetStreamETag(entity, streamProperty, operationContext), operationContext.ResponseMessage); } catch { WebUtil.Dispose(readStream); throw; } return(readStream); }