{"id":473,"date":"2013-07-26T11:49:02","date_gmt":"2013-07-26T11:49:02","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2013\/07\/26\/using-the-new-client-hooks-in-wcf-data-services-client\/"},"modified":"2020-01-09T02:53:50","modified_gmt":"2020-01-09T09:53:50","slug":"using-the-new-client-hooks-in-wcf-data-services-client","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/using-the-new-client-hooks-in-wcf-data-services-client\/","title":{"rendered":"Using the new client hooks in WCF Data Services Client"},"content":{"rendered":"<h3>What are the Request and Response Pipeline configurations in WCF Data Services Client?<\/h3>\n<p>In WCF Data Services 5.4 we added a new pattern to allow developers to hook into the client request and response pipelines. In the server, we have long had the concept of a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.data.services.dataserviceprocessingpipeline_events.aspx\">processing pipeline<\/a>. Developers can use the processing pipeline event to tweak how the server processes requests and responses. This concept has now been added to the client (though not as an event). The feature is exposed through the <code>Configurations<\/code> property on the <code>DataServiceContext<\/code>. On <code>Configurations<\/code> there are two properties, called <code>ResponsePipeline<\/code> and <code>RequestPipeline<\/code>. The <code>ResponsePipeline<\/code> contains configuration callbacks that influence reading to OData and materializing the results to CLR objects. The <code>RequestPipeline<\/code> contains configuration callbacks that influence the writing of CLR objects to the wire. Developers can then build on top of the new public API and compose higher level functionality.<\/p>\n<p>The explanation might be a bit abstract so let\u2019s move look at a real world example. The code below will document how to remove a property that is unnecessary on the client or that causes materialization issues. Previously this was difficult to do, and impossible if the payload was returning the newer JSON format, but this scenario is now trivially possible with the new hooks. Below is a code snippet to remove a specific property:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example1.cs\"><\/script><\/p>\n<p>This code is using the <code>OnEntryRead<\/code> response configuration method to remove the property. Behind the scenes what is happening is the <code>Microsoft.Data.ODataReader<\/code> calls <code>reader.Read()<\/code>. As it reads though the items, depending on the <code>ODataItem<\/code> type a call will be made to the all configuration callbacks of that type that are registered. A couple notes about this code:<\/p>\n<ol>\n<li>Since <code>ODataEntry.Properties<\/code> is an <code>IEnumerable&lt;ODataProperty&gt;<\/code> and not an <code>ICollection&lt;ODataProperty&gt;<\/code>, we need to replace the entire <code>IEnumerable<\/code> instead of just calling <code>ODataEntries.Properties.Remove()<\/code>.<\/li>\n<li><code>ResolveType<\/code> is used here to use the <code>TypeName<\/code> and get the <code>EntityType<\/code>, typically for a code generated <code>DataServiceContext<\/code> this method is automatically hooked up but if you are using a <code>DataServiceContext<\/code> directly then delegate code will need to be written.<\/li>\n<\/ol>\n<p>What if this scenario has to occur for other properties on the same type or properties on a different type? Let\u2019s make some changes to make this code a bit more reusable.<\/p>\n<p>Extension method for removing a property from an <code>ODataEntry<\/code>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example2.cs\"><\/script><\/p>\n<p>Extension method for removing a property from the <code>ODataEntry<\/code> on the selected type:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example3.cs\"><\/script><\/p>\n<p>And now finally the code that the developer would write to invoke the method above and set the configuration up:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example4.cs\"><\/script><\/p>\n<p>The original code is now broken down and is more reusable. Developers can use the <code>RemoveProperties<\/code> extension above to remove any property from a type that is in the <code>ODataEntry<\/code> payload. These extension methods can also be chained together.<\/p>\n<p>The example above shows how to use <code>OnEntryEnded<\/code>, but there are a number of other callbacks that can be used. Here is a complete list of configuration callbacks on the response pipeline:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example5.cs\"><\/script><\/p>\n<p>All of the configuration callbacks above with the exception of <code>OnEntityMaterialized<\/code> and <code>OnMessageReaderSettingsCreate<\/code> are called when the <code>ODataReader<\/code> is reading through the feed or entry. The <code>OnMessageReaderSettingsCreate<\/code> callback is called just prior to when the <code>ODataMessageWriter<\/code> is created and before any of the other callbacks are called. The <code>OnEntityMaterialized<\/code> is called after a new entity has been converted from the given <code>ODataEntry<\/code>. The callback allows developers to apply any fix-ups to an entity after it was converted.<\/p>\n<p>Now let\u2019s move on to a sample where we use a configuration on the <code>RequestPipeline<\/code> to skip writing a property to the wire. Below is an example of an extension method that can remove the specified properties before it is written out:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example6.cs\"><\/script><\/p>\n<p>As you can see we are following the same pattern as the extension method we wrote to <code>RemoveProperties<\/code> for the <code>ResponsePipeline<\/code>. In comparison to this extension method this function doesn\u2019t require the type resolving func, so it\u2019s a bit simpler. The type information is specified on the <code>OnEntryEnding<\/code> args in the <code>Entity<\/code> property. Again this example only touches on <code>ODataEntryEnding<\/code>. Below is the complete list of configuration callbacks that can be used:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/markdstafford\/6091320.js?file=example7.cs\"><\/script><\/p>\n<p>With the exception of <code>OnMessageWriterSettingsCreated<\/code>, the other configuration callbacks are called when the <code>ODataWriter<\/code> is writing information to the wire.<\/p>\n<p>In conclusion, the request and response pipelines offer ways to configure the how payloads are read and written to the wire. Let us know any other questions you might have to leverage this feature.<\/p>\n<p>Chris Robinson \u2013 OData Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What are the Request and Response Pipeline configurations in WCF Data Services Client? In WCF Data Services 5.4 we added a new pattern to allow developers to hook into the client request and response pipelines. In the server, we have long had the concept of a processing pipeline. Developers can use the processing pipeline event [&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":[65,78],"class_list":["post-473","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","tag-samples","tag-wcf-data-services"],"acf":[],"blog_post_summary":"<p>What are the Request and Response Pipeline configurations in WCF Data Services Client? In WCF Data Services 5.4 we added a new pattern to allow developers to hook into the client request and response pipelines. In the server, we have long had the concept of a processing pipeline. Developers can use the processing pipeline event [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/473","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=473"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/473\/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=473"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=473"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=473"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}