{"id":1073,"date":"2010-11-12T12:21:09","date_gmt":"2010-11-12T12:21:09","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2010\/11\/12\/named-resource-streams\/"},"modified":"2010-11-12T12:21:09","modified_gmt":"2010-11-12T12:21:09","slug":"named-resource-streams","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/named-resource-streams\/","title":{"rendered":"Named Resource Streams"},"content":{"rendered":"<\/p>\n<p class=\"MsoNormal\">One of the new WCF Data Services features in the <a href=\"https:\/\/www.microsoft.com\/downloads\/en\/details.aspx?FamilyID=d8334829-9b77-4ab2-bbdb-d71ceaca57e4&amp;displaylang=en\"><font color=\"#0000ff\">October 2010 CTP<\/font><\/a> is something called Named Resource Streams. <\/p>\n<\/p>\n<h4>Background<\/h4>\n<h2>\n<\/h2>\n<p class=\"MsoNormal\">Data Services already supports Media Link Entries which allows you to associate a single streamed blob with an entry. <span>&#160;<\/span>For example, you could have a Photo entry that lists the metadata about the photo and links directly to the photo itself. <\/p>\n<\/p>\n<p class=\"MsoNormal\">But what happens though if you have multiple versions of the Photo? <\/p>\n<\/p>\n<p class=\"MsoNormal\">Today you could model this with multiple MLEs, but doing so requires you to have multiple copies of the metadata for each version of the stream. <span>&#160;<\/span>Clearly this is not desirable when you have multiple versions of essentially the photo. <span>&#160;<\/span> <\/p>\n<\/p>\n<p class=\"MsoNormal\">It turns out that this is a very common scenario, common enough that we thought it needed to be supported without forcing people to use multiple MLEs. <span>&#160;<\/span>So, with this release we\u2019ve allowed an entry to have multiple streams associated with it such that you can now create services that do things such as expose a Photo entry with links to its print, web and thumbnail versions. <\/p>\n<\/p>\n<p class=\"MsoNormal\">Let\u2019s explore how to use this feature. <\/p>\n<\/p>\n<h4>Client-Side <\/h4>\n<h2>\n<\/h2>\n<p class=\"MsoNormal\">Once a producer exposes Named Resource Streams you have two ways to manipulate them on the client, the first is via new overloads of <span class=\"CodeChar\"><strong>GetReadStream(..)<\/strong><\/span> and <span class=\"CodeChar\"><strong>SetSaveStream(..)<\/strong><\/span> that take a stream name: <\/p>\n<\/p>\n<p class=\"Code\"><strong>\/\/ retrieve a person      <br \/>Person fred = (from p in context.People       <br \/><span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/span>where p.Name == &quot;Fred&quot;       <br \/><span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/span>select p).Single();       <\/p>\n<p>\/\/ set custom headers etc via args if needed.       <br \/>var args = new DataServiceRequestArgs();       <br \/>args.Headers.Add(\u2026);       <\/p>\n<p>\/\/ make the request to get the stream \u2018Photo\u2019 stream on the Fred entity.       <br \/>var response = context.GetReadStream(fred, &quot;Photo&quot;, args);       <br \/>Stream stream = response.Stream; <\/strong><\/p>\n<\/p>\n<p class=\"MsoNormal\">If you want to update the stream you use <span class=\"CodeChar\"><strong>SetWriteStream(..)<\/strong><\/span> something like this:     <\/p>\n<p><strong><span class=\"CodeChar\">var fileStream = new FileStream(&quot;C:\\\\fred.jpeg&quot;, FileMode.Open);        <br \/>context.SetSaveStream(person, &quot;Photo&quot;, fileStream, true, args);         <br \/>context.SaveChanges();<\/span> <\/strong><\/p>\n<\/p>\n<p class=\"MsoNormal\">The other option is to use the <span class=\"CodeChar\"><strong>StreamDescriptor<\/strong><\/span> which hangs off the entity\u2019s <span class=\"CodeChar\"><strong>EntityDescriptor<\/strong><\/span>, and carries information about the <span class=\"CodeChar\"><strong>SelfLink<\/strong><\/span>, <span class=\"CodeChar\"><strong>EditLink<\/strong><\/span> (often they are the same, but you can sometimes get and update the stream via different urls), <span class=\"CodeChar\"><strong>ETag<\/strong><\/span> and <span class=\"CodeChar\"><strong>ContentType<\/strong><\/span> of the Stream: <\/p>\n<\/p>\n<p class=\"Code\"><strong>\/\/ Get the entity descriptor for Fred      <br \/>var dscptor = context.GetEntityDescriptor(fred); <\/strong><\/p>\n<p><strong><\/strong><\/p>\n<p><strong><\/strong><\/p>\n<p class=\"Code\"><strong>\/\/ Get the \u2018Photo\u2019 StreamDescriptor      <br \/>var photoDscptor = dscptor.StreamDescriptors.Single(s =&gt; s.Name == &quot;Photo&quot;);       <br \/>Uri uriOfFredsPhoto = photoDscptor.SelfLink; <\/strong><\/p>\n<\/p>\n<p class=\"MsoNormal\">With the StreamDescriptor you can do low level network activities or perhaps use this Uri when rendering a webpage in the \u2018src\u2019 of an &lt;img&gt; tag. <\/p>\n<\/p>\n<h4>Server-Side <\/h4>\n<h2>\n<\/h2>\n<h5>Adding Named Resource Streams to your Model <\/h5>\n<h3>\n<\/h3>\n<p class=\"MsoNormal\">The first step to using Named Resource Streams is to add them into your model. Because data services supports 3 different types of data sources (Entity Framework, Reflection, Custom) there are three ways to add Named Resource Streams into your model. <\/p>\n<\/p>\n<h5><em>Entity Framework <\/em><\/h5>\n<h4>\n<\/h4>\n<p class=\"MsoNormal\">When using the Entity Framework adding a Named Resource Stream to an EntityType is pretty straight forward, you simply add a structural annotation into your Entity Framework EDMX file something like this: <\/p>\n<\/p>\n<p class=\"Code\"><strong>&lt;EntityType Name=&quot;Person&quot;&gt;      <br \/><span>&#160;&#160; <\/span>&lt;Key&gt;       <br \/><span>&#160;&#160;&#160;&#160; <\/span>&lt;PropertyRef Name=&quot;ID&quot; \/&gt;       <br \/><span>&#160;&#160; <\/span>&lt;\/Key&gt;       <br \/><span>&#160;&#160; <\/span>&lt;Property Name=&quot;ID&quot; Type=&quot;Edm.Int32&quot; Nullable=&quot;false&quot; \/&gt;       <br \/><span>&#160;&#160; <\/span>&lt;Property Name=&quot;Name&quot; Type=&quot;Edm.String&quot; Nullable=&quot;true&quot; \/&gt;       <br \/><span>&#160;&#160; <\/span>&lt;m:NamedStreams&gt;       <br \/><span>&#160;&#160;&#160;&#160;&#160;&#160; <\/span>&lt;m:NamedStream Name=&quot;PhotoThumbnail&quot; \/&gt;       <br \/><span>&#160;&#160;&#160;&#160;&#160;&#160; <\/span>&lt;m:NamedStream Name=&quot;Photo&quot; \/&gt;       <br \/><span>&#160;&#160; <\/span>&lt;\/m:NamedStreams&gt;       <br \/>&lt;\/EntityType&gt; <\/strong><\/p>\n<\/p>\n<p class=\"MsoNormal\">Here the the <span class=\"CodeChar\"><strong>m:NamedStreams<\/strong><\/span> element (xmlns:m=&quot;http:\/\/schemas.microsoft.com\/ado\/2007\/08\/dataservices\/metadata&quot;) indicates Person has two Named Resource Streams, Photo and PhotoThumbnail. <\/p>\n<\/p>\n<h5><em>Reflection Provider <\/em><\/h5>\n<h4>\n<\/h4>\n<p class=\"MsoNormal\">To add a Named Resource Streams to an EntityType using the <a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2010\/06\/11\/tip-56-writing-an-odata-service-using-the-reflection-provider.aspx\"><font color=\"#0000ff\">Reflection Provider<\/font><\/a> we added a new attribute called <span class=\"CodeChar\"><strong>NamedStreamAttribute<\/strong><\/span>: <\/p>\n<\/p>\n<p class=\"Code\"><strong>[NamedStream(\u201cPhotoThumbnail\u201d)]      <br \/>[NamedStream(\u201cPhoto\u201d)]       <br \/>public class Person       <br \/>{       <br \/><span>&#160; <\/span>public int ID {get;set;}       <br \/><span>&#160; <\/span>public string Name {get;set}       <br \/>} <\/strong><\/p>\n<\/p>\n<p class=\"MsoNormal\">This example is the Reflection provider equivalent of the Entity Framework example above. <\/p>\n<\/p>\n<h5><em>Custom Provider<\/em><\/h5>\n<h4><span class=\"Heading3Char\"><span style=\"font-weight: normal\"><\/span>      <\/p>\n<p>   <\/span><\/h4>\n<p class=\"MsoNormal\">When you write a custom provider (<a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2010\/01\/07\/data-service-providers-getting-started.aspx\"><font color=\"#0000ff\">see this series for more<\/font><\/a>) you add the Named Resource Streams via your implementation of <a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2010\/01\/08\/creating-a-data-service-provider-part-3-metadata.aspx\"><font color=\"#0000ff\">IDataServiceMetadataProvider<\/font><\/a>. <\/p>\n<\/p>\n<p class=\"MsoNormal\">To support this we added a new ResourceStreamInfo class which you can add to your ResourceType definitions something like this: <\/p>\n<\/p>\n<p class=\"Code\"><strong>ResourceType person = \u2026      <br \/>person.AddNamedStream(new ResourceStreamInfo(&quot;PhotoThumbnail&quot;));       <br \/>person.AddNamedStream(new ResourceStreamInfo(&quot;Photo&quot;)); <\/strong><\/p>\n<\/p>\n<h5><em><span class=\"Heading4Char\">$metadata<\/span> <\/em><\/h5>\n<p class=\"MsoNormal\"><span class=\"Heading4Char\"><\/span>No matter how you tell Data Services about your Named Resource Streams consumers always learn about Named Streams via $metadata, which is an EDMX file, so as you might guess we simply tell consumers about named streams using the same structured annotations we used in the Entity Framework provider example above. <\/p>\n<\/p>\n<h5>Implementing Named Resource Streams <\/h5>\n<h3>\n<\/h3>\n<p class=\"MsoNormal\">Next you have to implement a new interface called <span class=\"CodeChar\"><strong>IDataServiceStreamProvider2<\/strong><\/span> <\/p>\n<\/p>\n<p class=\"MsoNormal\">Implementing this interface is very similar to implementing <span class=\"CodeChar\"><strong>IDataServiceStreamProvider<\/strong><\/span> which Glenn explains well in his two part series (<a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/08\/04\/data-services-streaming-provider-series-implementing-a-streaming-provider-part-1.aspx\"><font color=\"#0000ff\">Part1<\/font><\/a> &amp; <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/09\/08\/data-services-streaming-provider-series-part-2-accessing-a-media-resource-stream-from-the-client.aspx\"><font color=\"#0000ff\">Part2<\/font><\/a>). <\/p>\n<\/p>\n<p class=\"MsoNormal\"><span class=\"CodeChar\"><strong>IDataServiceStreamProvider2<\/strong><\/span> extends <span class=\"CodeChar\"><strong>IDataServiceStreamProvider<\/strong><\/span> by adding some overloads to work with Named Resource Streams. <\/p>\n<\/p>\n<p class=\"MsoNormal\">The overloads always take a <span class=\"CodeChar\"><strong>ResourceStreamInfo<\/strong><\/span> from which you can learn which Named Resource Streams is targeted. When reading from or writing to the stream you also get the eTag for the stream and a flag indicating whether the eTag should be checked. <\/p>\n<\/p>\n<h4>Summary<\/h4>\n<h2>\n<\/h2>\n<p class=\"MsoNormal\">As you can see Named Resource Streams add a significant new feature to Data Services, which is very useful if you have any entities that contain metadata for anything that has multiple representations, like for example Photos or Videos. <\/p>\n<\/p>\n<p class=\"MsoNormal\">Named Resource Streams are very easy to use client-side and build upon our existing Stream capabilities on the server side. <\/p>\n<\/p>\n<p class=\"MsoNormal\">As always we are keen to hear your thoughts and feedback.    <\/p>\n<p><a href=\"https:\/\/twitter.com\/adjames\"><font color=\"#0000ff\">Alex James<\/font><\/a><font color=\"#0000ff\">      <br \/><\/font>Program Manager     <br \/>Microsoft <\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the new WCF Data Services features in the October 2010 CTP is something called Named Resource Streams. Background Data Services already supports Media Link Entries which allows you to associate a single streamed blob with an entry. &#160;For example, you could have a Photo entry that lists the metadata about the photo and [&hellip;]<\/p>\n","protected":false},"author":512,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1073","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata"],"acf":[],"blog_post_summary":"<p>One of the new WCF Data Services features in the October 2010 CTP is something called Named Resource Streams. Background Data Services already supports Media Link Entries which allows you to associate a single streamed blob with an entry. &#160;For example, you could have a Photo entry that lists the metadata about the photo and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/1073","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/users\/512"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=1073"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/1073\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3253"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=1073"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=1073"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=1073"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}