Feed Customization (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 uses the Open Data Protocol (OData) to expose data as a feed. OData supports both Atom and JavaScript Object Notation (JSON) formats for data feeds. When you use an Atom feed, OData provides a standard method to serialize data, such as entities and relationships, into an XML format that can be included in the body of HTTP message. OData defines a default entity-property mapping between the data that is contained in entities and Atom elements. For more information, see OData: Atom Format.

You may have an application scenario that requires that the property data returned by the data service be serialized in a customized manner rather than in the standard feed format. With OData, you can customize the serialization in a data feed so that properties of an entity may be mapped to unused elements and attributes of an entry or to custom elements of an entry in the feed.

Note

Feed customization is only supported for Atom feeds. Custom feeds are not returned when the JSON format is requested for the returned feed.

With WCF Data Services, you can define an alternate entity-property mapping for an Atom payload by manually applying attributes to entity types in the data model. The data source provider of the data service determines how you should apply these attributes.

Important

When you define custom feeds, you must guarantee that all entity properties that have custom mappings defined are included in the projection. When a mapped entity property is not included in the projection, data loss might occur. For more information, see Query Projections.

Customizing Feeds with the Entity Framework Provider

The data model used with the Entity Framework provider is represented as XML in the .edmx file. In this case, the attributes that define custom feeds are added to the EntityType and Property elements that represent entity types and properties in the data model. These feed customization attributes are not defined in [MC-CSDL]: Conceptual Schema Definition File Format, which is the format that the Entity Framework provider uses to define the data model. Therefore, you must declare feed customization attributes in a specific schema namespace, which is defined as m="https://schemas.microsoft.com/ado/2007/08/dataservices/metadata". The following XML fragment shows feed customization attributes applied to Property elements of the Products entity type that define the ProductName, ReorderLevel, and UnitsInStock properties.

<Property Name="ProductName" Type="String" Nullable="false" 
          MaxLength="40" Unicode="true" FixedLength="false"
          m:FC_TargetPath="SyndicationAuthorName"
          m:FC_ContentKind="text"
          m:FC_KeepInContent="true"
          />
<Property Name="UnitsInStock" Type="Int16"
          m:FC_TargetPath="UnitsInStock"
          m:FC_NsPrefix="Northwind"
          m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices"
          m:FC_KeepInContent="true"
          />
<Property Name="ReorderLevel" Type="Int16"
          m:FC_TargetPath="UnitsInStock/@ReorderLevel"
          m:FC_NsPrefix="Northwind"
          m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices"
          m:FC_KeepInContent="false"
          />

These attributes produce the following customized data feed for the Products entity set. In the customized data feed, the ProductName property value is displayed in both in the author element and as the ProductName property element, and the UnitsInStock property is displayed in a custom element that has its own unique namespace and with the ReorderLevel property as an attribute:

<entry xml:base="http://localhost:12345/Northwind.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/Northwind.svc/Products(1)</id>
  <title type="text" />
  <updated>2009-10-02T05:09:44Z</updated>
  <author>
    <name>Chai</name>
  </author>
  <link rel="edit" title="Products" href="Products(1)" />
  <link rel="https://schemas.microsoft.com/ado/2007/08/dataservices/related/Order_Details" 
        type="application/atom+xml;type=feed" title="Order_Details" 
        href="Products(1)/Order_Details" />
  <category term="NorthwindModel.Products" 
            scheme="https://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:ProductID m:type="Edm.Int32">1</d:ProductID>
      <d:ProductName>Chai</d:ProductName>
      <d:UnitsInStock m:type="Edm.Int16">39</d:UnitsInStock>
      <d:SupplierID m:type="Edm.Int32">1</d:SupplierID>
      <d:CategoryID m:type="Edm.Int32">1</d:CategoryID>
      <d:QuantityPerUnit>10 boxes x 20 bags</d:QuantityPerUnit>
      <d:UnitPrice m:type="Edm.Decimal">18.0000</d:UnitPrice>
      <d:UnitsOnOrder m:type="Edm.Int16">0</d:UnitsOnOrder>
      <d:Discontinued m:type="Edm.Boolean">false</d:Discontinued>
    </m:properties>
  </content>
  <Northwind:UnitsInStock 
    Northwind:ReorderLevel="10" 
    xmlns:Northwind="http://schemas.examples.microsoft.com/dataservices">39</Northwind:UnitsInStock>
</entry>

For more information, see How to: Customize Feeds with the Entity Framework Provider.

Note

Because extensions to the data model are not supported by the Entity Designer, you must manually modify the XML file that contains the data model. For more information about the .edmx file that is generated by the Entity Data Model tools, see .edmx File Overview (Entity Framework).

Custom Feed Attributes

The following table shows the XML attributes that customize feeds that you can add to the conceptual schema definition language (CSDL) that defines the data model. These attributes are equivalent to the properties of the EntityPropertyMappingAttribute used with the reflection provider.

Attribute name Description
FC_ContentKind Indicates the type of the content. The following keywords define syndication content types.

text: The property value is displayed in the feed as text.

html: The property value is displayed in the feed as HTML.

xhtml: The property value is displayed in the feed as XML-formatted HTML.

These keywords are equivalent to the values of the SyndicationTextContentKind enumeration used with the reflection provider.

This attribute is not supported when the FC_NsPrefix and FC_NsUri attributes are used.

When you specify a value of xhtml for the FC_ContentKind attribute, you must ensure that the property value contains properly formatted XML. The data service returns the value without performing any transformations. You must also ensure that any XML element prefixes in the returned XML have a namespace URI and prefix defined in the mapped feed.
FC_KeepInContent Indicates that the referenced property value should be included both in the content section of the feed and in the mapped location. Valid values are true and false. To make the resulting feed backward-compatible with earlier versions of WCF Data Services, specify a value of true to make sure that the value is included in the content section of the feed.
FC_NsPrefix The namespace prefix of the XML element in a non-syndication mapping. This attribute must be used with the FC_NsUri attribute and cannot be used with the FC_ContentKind attribute.
FC_NsUri The namespace URI of the XML element in a non-syndication mapping. This attribute must be used with the FC_NsPrefix attribute and cannot be used with the FC_ContentKind attribute.
FC_SourcePath The path of the property of the entity to which this feed mapping rule applies. This attribute is only supported when it is used in an EntityType element.

The SourcePath property cannot directly reference a complex type. For complex types, you must use a path expression where property names are separated by a backslash (/) character. For example, the following values are allowed for an entity type Person with an integer property Age and a complex property

Address:

Age

Address/Street

The SourcePath property cannot be set to a value that contains a space or any other character that is not valid in a property name.
FC_TargetPath The name of the target element of the resulting feed to map the property. This element can be an element defined by the Atom specification or a custom element.

The following keywords are predefined syndication target-path values that point to specific location in an OData feed.

SyndicationAuthorEmail: The atom:email child element of the atom:author element.

SyndicationAuthorName: The atom:name child element of the atom:author element.

SyndicationAuthorUri: The atom:uri child element of the atom:author element.

SyndicationContributorEmail: The atom:email child element of the atom:contributor element.

SyndicationContributorName: The atom:name child element of the atom:contributor element.

SyndicationContributorUri: The atom:uri child element of the atom:contributor element.

SyndicationCustomProperty: A custom property element. When mapping to a custom element, the target must be a path expression in which nested elements are separated by a backslash (/) and attributes are specified by an ampersand (@). In the following example, the string UnitsInStock/@ReorderLevel maps a property value to an attribute named ReorderLevel on a child element named UnitsInStock of the root entry element.

<Property Name="ReorderLevel" Type="Int16" m:FC_TargetPath="UnitsInStock/@ReorderLevel" m:FC_NsPrefix="Northwind" m:FC_NsUri="http://schemas.examples.microsoft.com/dataservices" m:FC_KeepInContent="false" />

When the target is a custom element name, the FC_NsPrefix and FC_NsUri attributes must also be specified.

SyndicationPublished: The atom:published element.

SyndicationRights: The atom:rights element.

SyndicationSummary: The atom:summary element.

SyndicationTitle: The atom:title element.

SyndicationUpdated: The atom:updated element.

These keywords are equivalent to the values of the SyndicationItemProperty enumeration used with the reflection provider.

Note

Attribute names and values are case-sensitive. Attributes can be applied either to the EntityType element or to one or more Property elements, but not to both.

Customizing Feeds with the Reflection Provider

To customize feeds for a data model that was implemented by using the reflection provider, add one or more instances of the EntityPropertyMappingAttribute attribute to the classes that represent entity types in the data model. The properties of the EntityPropertyMappingAttribute class correspond to the feed customization attributes that are described in the previous section. The following is an example of the declaration of the Order type, with custom feed mapping defined for both properties.

Note

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

[EntityPropertyMappingAttribute("Customer",
    SyndicationItemProperty.AuthorName,
    SyndicationTextContentKind.Plaintext, true)]
[EntityPropertyMapping("OrderId",
    SyndicationItemProperty.Title,
    SyndicationTextContentKind.Plaintext, false)]
[DataServiceKeyAttribute("OrderId")]
public class Order
<EntityPropertyMappingAttribute("Customer", _
    SyndicationItemProperty.AuthorName, _
    SyndicationTextContentKind.Plaintext, True)> _
<EntityPropertyMapping("OrderId", _
    SyndicationItemProperty.Title, _
    SyndicationTextContentKind.Plaintext, False)> _
<DataServiceKeyAttribute("OrderId")> _
Public Class Order

These attributes produce the following customized data feed for the Orders entity set. In this customized feed, the OrderId property value displays only in the title element of the entry and the Customer property value displays both in the author element and as the Customer property element:

<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:11:11Z</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" />
  <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>

For more information, see How to: Customize Feeds with the Reflection Provider.

Customizing Feeds with a Custom Data Service Provider

Feed customization for a data model defined by using a custom data service provider is defined for a resource type by calling the AddEntityPropertyMappingAttribute on the ResourceType that represents an entity type in the data model. For more information, see Custom Data Service Providers.

Consuming Custom Feeds

When your application directly consumes an OData feed, it must be able to process any customized elements and attributes in the returned feed. When you have implemented custom feeds in your data model, regardless of the data service provider, the $metadata endpoint returns custom feed information as custom feed attributes in the CSDL returned by the data service. When you use the Add Service Reference dialog or the datasvcutil.exe tool to generate client data service classes, the customized feed attributes are used to guarantee that requests and responses to the data service are handled correctly.

Feed Customization Considerations

You should consider the following when defining custom feed mappings.

  • The WCF Data Services client treats mapped elements in a feed as empty when they contain only white space. Because of this, mapped elements that contain only white space are not materialized on the client with the same white space. To preserve this white space on the client, you must set the value of KeepInContext to true in the feed mapping attribute.

Versioning Requirements

Feed customization has the following OData protocol versioning requirements:

  • Feed customization requires that both the client and data service support version 2.0 of the OData protocol and later versions.

For more information, see Data Service Versioning.

See also