private Stream GetWriteStreamInternal(object entity, ResourceProperty streamProperty, string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext) { this.ThrowIfDisposed(); CheckArgumentNull(entity, "entity"); CheckArgumentNull(operationContext, "operationContext"); ValidateEntity(entity, streamProperty); DSPMediaResource mediaResource; if (!this.streamStorage.TryGetMediaResource(entity, streamProperty, out mediaResource)) { mediaResource = this.streamStorage.CreateMediaResource(entity, streamProperty); } ValidateETag(etag, checkETagForEquality, operationContext, mediaResource); if (operationContext.RequestMethod == "POST") { if (streamProperty != null) { throw new InvalidOperationException("POST is allowed only for default streams."); } string slug = operationContext.RequestHeaders["Slug"]; if (!string.IsNullOrEmpty(slug)) { this.ApplySlugHeader(slug, entity); } } else if (operationContext.RequestMethod != "PUT") { throw new InvalidOperationException("Unsupported http method '" + operationContext.RequestMethod + "'."); } mediaResource.ContentType = operationContext.RequestHeaders["Content-Type"]; if (string.IsNullOrEmpty(mediaResource.ContentType)) { throw new InvalidOperationException("Content-Type header missing."); } mediaResource.Etag = DSPMediaResource.GenerateStreamETag(); return(mediaResource.GetWriteStream()); }
/// <summary> /// Validates etag arguments /// </summary> /// <param name="etag">etag value</param> /// <param name="checkETagForEquality">If the etag was sent as the value of an If-None-Match request header, the value of �checkETagForEquality� will be set to false</param> private static void ValidateETag(string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext, DSPMediaResource mediaResource) { if (checkETagForEquality.HasValue) { CheckStringArgumentNull(etag, "etag"); } else if (!string.IsNullOrEmpty(etag)) { throw new ArgumentException("'etag' argument should be null when 'checkETagForEquality' argument has no value"); } // We do not check etag for POST if (operationContext.RequestMethod.Equals("POST", StringComparison.OrdinalIgnoreCase)) { return; } string currentEtag = mediaResource.Etag; if (!operationContext.RequestMethod.Equals("GET", StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrEmpty(currentEtag) && !checkETagForEquality.HasValue) { throw new DataServiceException(400, "Since the target media resource has an etag defined, If-Match/If-Not-Match HTTP header must be specified."); } } if (checkETagForEquality.HasValue) { if (checkETagForEquality.Value == true && etag != currentEtag) { throw new DataServiceException(412, "If-Match precondition failed for target media resource. Thrown by DSPStreamProvider."); } if (checkETagForEquality.Value == false && etag == currentEtag) { if (operationContext.RequestMethod.Equals("GET", StringComparison.OrdinalIgnoreCase)) { throw new DataServiceException(304, "No Change, Thrown by DSPStreamProvider."); } else if (operationContext.RequestMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase)) { throw new DataServiceException(400, "If-None-Match HTTP header cannot be specified for PUT operations. Thrown by DSPStreamProvider."); } else if (operationContext.RequestMethod.Equals("DELETE", StringComparison.OrdinalIgnoreCase)) { throw new DataServiceException(400, "If-None-Match HTTP header cannot be specified for DELETE operations. Thrown by DSPStreamProvider."); } else { throw new NotSupportedException(); } } } }
internal static DSPServiceDefinition SetUpNamedStreamService() { DSPMetadata metadata = new DSPMetadata("NamedStreamIDSPContainer", "NamedStreamTest"); // entity with streams ResourceType entityWithNamedStreams = metadata.AddEntityType("EntityWithNamedStreams", null, null, false); metadata.AddKeyProperty(entityWithNamedStreams, "ID", typeof(int)); metadata.AddPrimitiveProperty(entityWithNamedStreams, "Name", typeof(string)); ResourceProperty streamInfo1 = new ResourceProperty("Stream1", ResourcePropertyKind.Stream, ResourceType.GetPrimitiveResourceType(typeof(Stream))); entityWithNamedStreams.AddProperty(streamInfo1); ResourceProperty streamInfo2 = new ResourceProperty("Stream2", ResourcePropertyKind.Stream, ResourceType.GetPrimitiveResourceType(typeof(Stream))); entityWithNamedStreams.AddProperty(streamInfo2); // entity1 with streams ResourceType entityWithNamedStreams1 = metadata.AddEntityType("EntityWithNamedStreams1", null, null, false); metadata.AddKeyProperty(entityWithNamedStreams1, "ID", typeof(int)); metadata.AddPrimitiveProperty(entityWithNamedStreams1, "Name", typeof(string)); ResourceProperty refStreamInfo1 = new ResourceProperty("RefStream1", ResourcePropertyKind.Stream, ResourceType.GetPrimitiveResourceType(typeof(Stream))); entityWithNamedStreams1.AddProperty(refStreamInfo1); // entity2 with streams ResourceType entityWithNamedStreams2 = metadata.AddEntityType("EntityWithNamedStreams2", null, null, false); metadata.AddKeyProperty(entityWithNamedStreams2, "ID", typeof(string)); metadata.AddPrimitiveProperty(entityWithNamedStreams2, "Name", typeof(string)); ResourceProperty collectionStreamInfo = new ResourceProperty("ColStream", ResourcePropertyKind.Stream, ResourceType.GetPrimitiveResourceType(typeof(Stream))); entityWithNamedStreams2.AddProperty(collectionStreamInfo); ResourceSet set1 = metadata.AddResourceSet("MySet1", entityWithNamedStreams); ResourceSet set2 = metadata.AddResourceSet("MySet2", entityWithNamedStreams1); ResourceSet set3 = metadata.AddResourceSet("MySet3", entityWithNamedStreams2); // add navigation property to entityWithNamedStreams metadata.AddResourceReferenceProperty(entityWithNamedStreams, "Ref", set2, entityWithNamedStreams1); metadata.AddResourceSetReferenceProperty(entityWithNamedStreams, "Collection", set3, entityWithNamedStreams2); metadata.AddResourceSetReferenceProperty(entityWithNamedStreams2, "Collection1", set2, entityWithNamedStreams1); DSPServiceDefinition service = new DSPServiceDefinition(); service.Metadata = metadata; service.MediaResourceStorage = new DSPMediaResourceStorage(); service.SupportMediaResource = true; service.SupportNamedStream = true; service.ForceVerboseErrors = true; service.PageSizeCustomizer = (config, type) => { config.SetEntitySetPageSize("MySet3", 1); }; // populate data DSPContext context = new DSPContext(); DSPResource entity1 = new DSPResource(entityWithNamedStreams); { context.GetResourceSetEntities("MySet1").Add(entity1); entity1.SetValue("ID", 1); entity1.SetValue("Name", "Foo"); DSPMediaResource namedStream1 = service.MediaResourceStorage.CreateMediaResource(entity1, streamInfo1); namedStream1.ContentType = "image/jpeg"; byte[] data1 = new byte[] { 0, 1, 2, 3, 4 }; namedStream1.GetWriteStream().Write(data1, 0, data1.Length); DSPMediaResource namedStream2 = service.MediaResourceStorage.CreateMediaResource(entity1, streamInfo2); namedStream2.ContentType = "image/jpeg"; byte[] data2 = new byte[] { 0, 1, 2, 3, 4 }; namedStream2.GetWriteStream().Write(data2, 0, data2.Length); } DSPResource entity2 = new DSPResource(entityWithNamedStreams1); { context.GetResourceSetEntities("MySet2").Add(entity2); entity2.SetValue("ID", 3); entity2.SetValue("Name", "Bar"); DSPMediaResource refNamedStream1 = service.MediaResourceStorage.CreateMediaResource(entity2, refStreamInfo1); refNamedStream1.ContentType = "image/jpeg"; byte[] data1 = new byte[] { 0, 1, 2, 3, 4 }; refNamedStream1.GetWriteStream().Write(data1, 0, data1.Length); // set the navigation property entity1.SetValue("Ref", entity2); } { DSPResource entity3 = new DSPResource(entityWithNamedStreams2); context.GetResourceSetEntities("MySet3").Add(entity3); entity3.SetValue("ID", "ABCDE"); entity3.SetValue("Name", "Bar"); DSPMediaResource stream = service.MediaResourceStorage.CreateMediaResource(entity3, collectionStreamInfo); stream.ContentType = "image/jpeg"; byte[] data1 = new byte[] { 0, 1, 2, 3, 4 }; stream.GetWriteStream().Write(data1, 0, data1.Length); entity3.SetValue("Collection1", new List <DSPResource>() { entity2 }); DSPResource entity4 = new DSPResource(entityWithNamedStreams2); context.GetResourceSetEntities("MySet3").Add(entity4); entity4.SetValue("ID", "XYZ"); entity4.SetValue("Name", "Foo"); DSPMediaResource stream1 = service.MediaResourceStorage.CreateMediaResource(entity3, collectionStreamInfo); stream1.ContentType = "image/jpeg"; stream1.GetWriteStream().Write(data1, 0, data1.Length); entity4.SetValue("Collection1", new List <DSPResource>() { entity2 }); entity1.SetValue("Collection", new List <DSPResource>() { entity3, entity4 }); } service.DataSource = context; return(service); }