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.
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.
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
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="http://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
<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="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://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="http://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="http://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.
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.
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.
||Indicates the type of the content. The following keywords define syndication content types.
These keywords are equivalent to the values of the SyndicationTextContentKind enumeration used with the reflection provider.
This attribute is not supported when the
When you specify a value of
||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
||The namespace prefix of the XML element in a non-syndication mapping. This attribute must be used with the
||The namespace URI of the XML element in a non-syndication mapping. This attribute must be used with the
||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
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 (
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.
||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.
When the target is a custom element name, the
These keywords are equivalent to the values of the SyndicationItemProperty enumeration used with the reflection provider.
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.
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
OrderIdproperty 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="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://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="http://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="http://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 whitespace. Because of this, mapped elements that contain only whitespace are not materialized on the client with the same whitespace. To preserve this whitespace on the client, you must set the value of
truein the feed mapping attribute.
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.