How to: Customize Feeds with the Reflection Provider (WCF Data Services)

Important

WCF Data Services has been deprecated and will no longer be available for download from the Microsoft Download Center. WCF Data Services supported earlier versions of the Microsoft OData (V1-V3) protocol only and has not been under active development. OData V1-V3 has been superseded by OData V4, which is an industry standard published by OASIS and ratified by ISO. OData V4 is supported through the OData V4 compliant core libraries available at Microsoft.OData.Core. Support documentation is available at OData.Net, and the OData V4 service libraries are available at Microsoft.AspNetCore.OData.

RESTier is the successor to WCF Data Services. RESTier helps you bootstrap a standardized, queryable, HTTP-based REST interface in minutes. Like WCF Data Services before it, Restier provides simple and straightforward ways to shape queries and intercept submissions before and after they hit the database. And like Web API + OData, you still have the flexibility to add your own custom queries and actions with techniques you're already familiar with.

WCF Data Services enables you to customize the Atom serialization in a data service response so that properties of an entity may be mapped to unused elements that are defined in the AtomPub protocol. This topic shows how to define mapping attributes for the entity types in a data model that is defined by using the reflection provider. For more information, see Feed Customization.

The data model for this example is defined in the topic How to: Create a Data Service Using the Reflection Provider

Example

In the following example, both properties of the Order type are mapped to existing Atom elements. The Product property of the Item type is mapped to a custom feed attribute in a separate namespace.

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;

namespace CustomDataService
{
    [EntityPropertyMappingAttribute("Customer",
        SyndicationItemProperty.AuthorName,
        SyndicationTextContentKind.Plaintext, true)]
    [EntityPropertyMapping("OrderId",
        SyndicationItemProperty.Title,
        SyndicationTextContentKind.Plaintext, false)]
    [DataServiceKeyAttribute("OrderId")]
    public class Order
    {
        public int OrderId { get; set; }
        public string Customer { get; set; }
        public IList<Item> Items { get; set; }
    }
    [EntityPropertyMappingAttribute("Product", "productname",
     "orders", "http://schema.examples.microsoft.com/dataservices", true)]
    [DataServiceKeyAttribute("Product")]
    public class Item
    {
        public string Product { get; set; }
        public int Quantity { get; set; }
    }
    public partial class OrderItemData
    {
        #region Populate Service Data
        static IList<Order> _orders;
        static IList<Item> _items;
        static OrderItemData()
        {
            _orders = new Order[]{
              new Order(){ OrderId=0, Customer = "Peter Franken", Items = new List<Item>()},
              new Order(){ OrderId=1, Customer = "Ana Trujillo", Items = new List<Item>()}};
            _items = new Item[]{
              new Item(){ Product="Chai", Quantity=10 },
              new Item(){ Product="Chang", Quantity=25 },
              new Item(){ Product="Aniseed Syrup", Quantity = 5 },
              new Item(){ Product="Chef Anton's Cajun Seasoning", Quantity=30}};
            _orders[0].Items.Add(_items[0]);
            _orders[0].Items.Add(_items[1]);
            _orders[1].Items.Add(_items[2]);
            _orders[1].Items.Add(_items[3]);
        }
        #endregion
        public IQueryable<Order> Orders
        {
            get { return _orders.AsQueryable(); }
        }
        public IQueryable<Item> Items
        {
            get { return _items.AsQueryable(); }
        }
    }

    public class OrderItems : DataService<OrderItemData>
    {
        // This method is called only once to initialize
        //service-wide policies.
        public static void InitializeService(DataServiceConfiguration
                                             config)
        {
            config.SetEntitySetAccessRule("Orders",
               EntitySetRights.AllRead |
               EntitySetRights.AllWrite);
            config.SetEntitySetAccessRule("Items",
                EntitySetRights.AllRead |
                EntitySetRights.AllWrite);
            config.DataServiceBehavior.MaxProtocolVersion =
                DataServiceProtocolVersion.V2;
        }
    }
}
Imports System.Collections.Generic
Imports System.Data.Services
Imports System.Data.Services.Common
Imports System.Linq

Namespace CustomDataService
    <EntityPropertyMappingAttribute("Customer", _
        SyndicationItemProperty.AuthorName, _
        SyndicationTextContentKind.Plaintext, True)> _
    <EntityPropertyMapping("OrderId", _
        SyndicationItemProperty.Title, _
        SyndicationTextContentKind.Plaintext, False)> _
    <DataServiceKeyAttribute("OrderId")> _
    Public Class Order
        Private _orderId As Integer
        Private _customer As String
        Private _items As IList(Of Item)
        Public Property OrderId() As Integer
            Get
                Return _orderId
            End Get
            Set(ByVal value As Integer)
                _orderId = value
            End Set
        End Property
        Public Property Customer() As String
            Get
                Return _customer
            End Get
            Set(ByVal value As String)
                _customer = value
            End Set
        End Property
        Public Property Items() As IList(Of Item)
            Get
                Return _items
            End Get
            Set(ByVal value As IList(Of Item))
                _items = value
            End Set
        End Property
    End Class
    <EntityPropertyMappingAttribute("Product", "productname", _
        "orders", "http://schema.examples.microsoft.com/dataservices", True)> _
    <DataServiceKeyAttribute("Product")> _
    Public Class Item
        Private _product As String
        Private _quantity As Integer
        Public Property Product() As String
            Get
                Return _product
            End Get
            Set(ByVal value As String)
                _product = value
            End Set
        End Property
        Public Property Quantity() As Integer
            Get
                Return _quantity
            End Get
            Set(ByVal value As Integer)
                _quantity = value
            End Set
        End Property
    End Class
    Partial Public Class OrderItemData
#Region "Populate Service Data"
        Shared _orders As IList(Of Order)
        Shared _items As IList(Of Item)
        Sub New()
            _orders = New Order() { _
                New Order() With {.OrderId = 0, .Customer = "Peter Franken", .Items = New List(Of Item)()}, _
              New Order() With {.OrderId = 1, .Customer = "Ana Trujillo", .Items = New List(Of Item)()}}
            _items = New Item() { _
              New Item() With {.Product = "Chai", .Quantity = 10}, _
              New Item() With {.Product = "Chang", .Quantity = 25}, _
              New Item() With {.Product = "Aniseed Syrup", .Quantity = 5}, _
              New Item() With {.Product = "Chef Anton's Cajun Seasoning", .Quantity = 30}}
            _orders(0).Items.Add(_items(0))
            _orders(0).Items.Add(_items(1))
            _orders(1).Items.Add(_items(2))
            _orders(1).Items.Add(_items(3))
        End Sub
#End Region
        Public ReadOnly Property Orders() As IQueryable(Of Order)
            Get
                Return _orders.AsQueryable()
            End Get
        End Property
        Public ReadOnly Property Items() As IQueryable(Of Item)
            Get
                Return _items.AsQueryable()
            End Get
        End Property
    End Class
    Public Class OrderItems
        Inherits DataService(Of OrderItemData)
        ' This method is called only once to initialize
        ' service-wide policies.
        Shared Sub InitializeService(ByVal config As DataServiceConfiguration)
            config.SetEntitySetAccessRule("Orders", _
                                          EntitySetRights.AllRead _
                                          Or EntitySetRights.AllWrite)
            config.SetEntitySetAccessRule("Items", _
                                          EntitySetRights.AllRead _
                                          Or EntitySetRights.AllWrite)
            config.DataServiceBehavior.MaxProtocolVersion =
                DataServiceProtocolVersion.V2
        End Sub
    End Class
End Namespace

Example

The previous example returns the following result for the URI http://myservice/OrderItems.svc/Orders(0)?$expand=Items.

<entry xml:base="http://localhost:12345/OrderItems.svc/" 
       xmlns:d="https://schemas.microsoft.com/ado/2007/08/dataservices" 
       xmlns:m="https://schemas.microsoft.com/ado/2007/08/dataservices/metadata" 
       xmlns="http://www.w3.org/2005/Atom">
  <id>http://localhost:12345/OrderItems.svc/Orders(0)</id>
  <title type="text">0</title>
  <updated>2009-07-25T21:12:30Z</updated>
  <author>
    <name>Peter Franken</name>
  </author>
  <link rel="edit" title="Order" href="Orders(0)" />
  <link rel="https://schemas.microsoft.com/ado/2007/08/dataservices/related/Items" 
        type="application/atom+xml;type=feed" title="Items" href="Orders(0)/Items">
    <m:inline>
      <feed>
        <title type="text">Items</title>
        <id>http://localhost:12345/OrderItems.svc/Orders(0)/Items</id>
        <updated>2009-07-25T21:12:30Z</updated>
        <link rel="self" title="Items" href="Orders(0)/Items" />
        <entry>
          <id>http://localhost:12345/OrderItems.svc/Items('Chai')</id>
          <title type="text" />
          <updated>2009-07-25T21:12:30Z</updated>
          <author>
            <name />
          </author>
          <link rel="edit" title="Item" href="Items('Chai')" />
          <category term="CustomDataService.Item" 
                    scheme="https://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
          <content type="application/xml">
            <m:properties>
              <d:Product>Chai</d:Product>
              <d:Quantity m:type="Edm.Int32">10</d:Quantity>
            </m:properties>
          </content>
          <orders:productname 
            xmlns:orders="http://schema.examples.microsoft.com/dataservices">Chai</orders:productname>
        </entry>
        <entry>
          <id>http://localhost:12345/OrderItems.svc/Items('Chang')</id>
          <title type="text" />
          <updated>2009-07-25T21:12:30Z</updated>
          <author>
            <name />
          </author>
          <link rel="edit" title="Item" href="Items('Chang')" />
          <category term="CustomDataService.Item" 
                    scheme="https://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
          <content type="application/xml">
            <m:properties>
              <d:Product>Chang</d:Product>
              <d:Quantity m:type="Edm.Int32">25</d:Quantity>
            </m:properties>
          </content>
          <orders:productname 
            xmlns:orders="http://schema.examples.microsoft.com/dataservices">Chang</orders:productname>
        </entry>
      </feed>
    </m:inline>
  </link>
  <category term="CustomDataService.Order" 
            scheme="https://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:Customer>Peter Franken</d:Customer>
    </m:properties>
  </content>
</entry>

See also