locked
Any update to docs, examples for WCF support of OData annotations? RRS feed

  • Question

  • The recent WCF Data Service 5.3 and 5.4 release notes mentioned improvements in support for OData 3.0 annotations.  However, the only mention I can find of how to access OData annotations in WCF is this "Vocabularies in WCF" article from 2011.

    Is this 2 year old article still current/valid and representative of WCF's current access to OData annotations?  Or is there something more recent that reflects WCF developments of the past 2 years? Anything? Please?

    Thanks,

    -Danny

    P.S. My primary interest is how to produce OData annotations in a WCF Data Service that does not use a EDM data model. I've written my own provider for POCOs using the query engine from the WCF Data Toolkit.  Secondary interest is how clients can consume/access those OData annotations using Service Reference generated proxy classes.


    http://dannythorpe.com

    Thursday, June 13, 2013 6:02 PM

Answers

  • To write custom instance annotations using WCF Data Services, you will need to set the ODataWriterFactory property on the DataService, which is a func that takes an ODataWriter and returns an DataServiceODataWriter. You need to implement your own subclass to write the annotations.

    In the example below, the service will write a custom instance annotation at the end of every feed. Similarly, you can override the method WriteStart(DataServiceODataWriterEntryArgs args) to add annotations on entries.

        public class Service : DataService<MyDataProvider>
        {
            public Service ()
            {
                this.ODataWriterFactory =
                    (odataWriter) =>
                    {
                        return new CustomDataServiceODataWriter(odataWriter);
                    };
            }
    
            public static void InitializeService(DataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule("*", EntitySetRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
                config.UseVerboseErrors = true;
            }
    
        }
    
        public class CustomDataServiceODataWriter : DataServiceODataWriter
        {
            public CustomDataServiceODataWriter(ODataWriter odataWriter) 
                : base(odataWriter)
            {
            }
    
            public override void WriteStart(DataServiceODataWriterFeedArgs args)
            {
                base.WriteStart(args);
                args.Feed.InstanceAnnotations.Add(new ODataInstanceAnnotation("MyNamespace.CustomAnnotation1", new ODataPrimitiveValue("Some annotation")));
            }
    
            public override void WriteStart(DataServiceODataWriterEntryArgs args)
            {
                base.WriteStart(args);
            }
        }

    From the client side, make sure the context’s MaxProtocolVersion is set to V3.

    Then you need to set the Prefer header value to "odata.include-annotations=*". This tells the server to include all custom instance annotations on the response.

    Finally, to access the annotations, use the context.Configuration.ResponsePipeline to have access to the ODataFeed and its instance annotations.

    For example

        var context = new DataServiceContext(serviceUri, DataServiceProtocolVersion.V3);
        context.SendingRequest2 += (sender, eventArgs) => ((HttpWebRequestMessage)eventArgs.RequestMessage).SetHeader("Prefer", "odata.include-annotations=*");
        context.Configurations.ResponsePipeline.OnFeedEnded((readingFeedArgs) => Console.WriteLine(readingFeedArgs.Feed.InstanceAnnotations.SingleOrDefault()));
    	



    Thursday, June 13, 2013 10:48 PM
    Moderator

All replies

  • To write custom instance annotations using WCF Data Services, you will need to set the ODataWriterFactory property on the DataService, which is a func that takes an ODataWriter and returns an DataServiceODataWriter. You need to implement your own subclass to write the annotations.

    In the example below, the service will write a custom instance annotation at the end of every feed. Similarly, you can override the method WriteStart(DataServiceODataWriterEntryArgs args) to add annotations on entries.

        public class Service : DataService<MyDataProvider>
        {
            public Service ()
            {
                this.ODataWriterFactory =
                    (odataWriter) =>
                    {
                        return new CustomDataServiceODataWriter(odataWriter);
                    };
            }
    
            public static void InitializeService(DataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule("*", EntitySetRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
                config.UseVerboseErrors = true;
            }
    
        }
    
        public class CustomDataServiceODataWriter : DataServiceODataWriter
        {
            public CustomDataServiceODataWriter(ODataWriter odataWriter) 
                : base(odataWriter)
            {
            }
    
            public override void WriteStart(DataServiceODataWriterFeedArgs args)
            {
                base.WriteStart(args);
                args.Feed.InstanceAnnotations.Add(new ODataInstanceAnnotation("MyNamespace.CustomAnnotation1", new ODataPrimitiveValue("Some annotation")));
            }
    
            public override void WriteStart(DataServiceODataWriterEntryArgs args)
            {
                base.WriteStart(args);
            }
        }

    From the client side, make sure the context’s MaxProtocolVersion is set to V3.

    Then you need to set the Prefer header value to "odata.include-annotations=*". This tells the server to include all custom instance annotations on the response.

    Finally, to access the annotations, use the context.Configuration.ResponsePipeline to have access to the ODataFeed and its instance annotations.

    For example

        var context = new DataServiceContext(serviceUri, DataServiceProtocolVersion.V3);
        context.SendingRequest2 += (sender, eventArgs) => ((HttpWebRequestMessage)eventArgs.RequestMessage).SetHeader("Prefer", "odata.include-annotations=*");
        context.Configurations.ResponsePipeline.OnFeedEnded((readingFeedArgs) => Console.WriteLine(readingFeedArgs.Feed.InstanceAnnotations.SingleOrDefault()));
    	



    Thursday, June 13, 2013 10:48 PM
    Moderator
  • Wednesday, July 3, 2013 9:01 PM