Reputation: 45283
There are lots of examples of using ODataConventionModelBuilder
with simple, contrived models, often just a single class.
But there's nothing that actually explains what the conventions are; how to code a model that complies with convention. There's no official documentation for it.
So what's the convention?
Upvotes: 6
Views: 1385
Reputation: 16757
The conventions used in ODataConventionModelBuilder are described here.
As for how to code a model that complies with the conventions, that is pretty straight forward, or rather you don't need to code a model to the conventions at all. The conventions exist to simplify and standardize how an EF model is expressed in an OData Edm Model. If you find yourself manually enabling features, then you might find there is a convention that can automate this process for you. Understanding what the conventions are might help.
Your answer @LukePuplett describes some of the EF Code First conventions, they don't really apply here, not all directly anyway. I don't want to say you were wrong... ;)
The following is derived from the source code for ConventionModelBuilder.
NOTE: ordering is important here.
AbstractTypeDiscoveryConvention
configures all structural types backed by an abstract CLR type as abstract.
DataContractAttributeEdmTypeConvention
Configures classes that have the DataContractAttribute
to follow DataContract serialization/deserialization rules.
NotMappedAttributeConvention
Ignores properties with the NotMappedAttribute from IEdmStructuredType
NotMappedAttributeConvention
MUST run before EntityKeyConvention
, or it will allow Keys to be excluded from the modelDataMemberAttributeEdmPropertyConvention
Configures properties that have DataMemberAttribute
as optional or required on their edm type.
IgnoreDataMemberAttribute
, but it will not explicitly add them eitherDerivedTypeConstraintAttributeConvention
Adds Derived Type Constraints to the Model if required
RequiredAttributeEdmPropertyConvention
Marks properties that have RequiredAttribute
as non-optional on their edm type.
DefaultValueAttributeEdmPropertyConvention
Sets default value for properties that have DefaultValueAttribute
ConcurrencyCheckAttributeEdmPropertyConvention
Marks properties that have ConcurrencyCheckAttribute
as non-optional on their EDM type.
TimestampAttributeEdmPropertyConvention
Annotates a single column in a Type as the Timestamp column, even if multiple columns are annotated with the TimestampAttribute
.
This is due to a SQL limitation table (the underlying concept this attribute is bounded to) that only supports one row version column per table.
ColumnAttributeEdmPropertyConvention
Marks properties that have ColumnAttribute
as the target EDM type.
KeyAttributeEdmPropertyConvention
Configures properties that have the KeyAttribute
as keys in the IEdmEntityType
KeyAttributeEdmPropertyConvention
MUST run before EntityKeyConvention
EntityKeyConvention
This convention configures properties that are named 'ID' (case-insensitive) or {EntityName}+ID (case-insensitive) as the key.
ComplexTypeAttributeConvention
Removes primitive properties that are exposed through ComplexType definitions from the IEdmEntityType
IgnoreDataMemberAttributeEdmPropertyConvention
Removes properties that have IgnoreDataMemberAttribute
from their edm type.
DataContract
and DataMemberAttribute
is present on this property, then the property will not be removed, DataMemberAttribute
takes precedenceNotFilterableAttributeEdmPropertyConvention
Configures a column with fluent IsNotFilterable()
if it has a NotFilterableAttribute
annotation. This will specify that the property cannot be used in the $filter
OData query option.
NonFilterableAttribute
and its related NonFilterableAttributeEdmPropertyConvention
NonFilterableAttributeEdmPropertyConvention
Configures a column with fluent IsNotFilterable()
if it has a NonFilterableAttribute
annotation. This will specify that the property cannot be used in the $filter
OData query option.
NotFilterableAttribute
and its related NotFilterableAttributeEdmPropertyConvention
;NotSortableAttributeEdmPropertyConvention
Configures a column with fluent IsNotSortable()
if it has a NotSortableAttribute
annotation. This will specify that the property cannot be used in the $orderby
OData query option.
UnsortableAttributeEdmPropertyConvention
Configures a column with fluent IsNotSortable()
if it has a UnsortableAttribute
annotation. This will specify that the property cannot be used in the $orderby
OData query option.
NotNavigableAttributeEdmPropertyConvention
Configures a column with fluent IsNotNavigable()
if it has the NotNavigableAttribute
annotation. This will specify that the property cannot be navigated in OData query.
$expand
, it means that the propert cannot be used to traverse to the associated resource using an Entity Path, for instance if ProductType
had this attribute, and was a navigation property that returned a ProductType
reference, the following OData path would not be servived: ~/api/products(112)/ProductType
this is a feature from the updates to support Containment.NotExpandableAttributeEdmPropertyConvention
Configures a column with fluent IsNotExpandable()
if it has a NotExpandableAttribute
annotation. This will specify that the property cannot be used in the $expand OData query option.
NotCountableAttributeEdmPropertyConvention
Configures a column with fluent IsNotCountable()
if it has a NotCountableAttribute
annotation. This will specify that the $count cannot be applied on the property.
MediaTypeAttributeConvention
Configures a class with fluent MediaType()
which marks this entity type as media type.
AutoExpandAttributeEdmPropertyConvention
Configured the AutoExpand feature of a column when it has the AutoExpandAttribute
annotation.
AutoExpandAttributeEdmTypeConvention
When AutoExpandAttribute
is placed on a class it can specify all navigation properties are auto expanded.
MaxLengthAttributeEdmPropertyConvention
Configures string or binary properties that have the MaxLengthAttribute
annotation.
PageAttributeEdmPropertyConvention
Sets the page size and Max Top of the entity type based on the PageAttribute
annotation if present on any of the properties in the class.
PageAttributeEdmTypeConvention
Sets the page size and Max Top of the entity type based on the PageAttribute
annotation on the class.
ExpandAttributeEdmPropertyConvention
Configures OData $expand
query option for navigation columns with ExpandAttribute
annotation.
ExpandAttributeEdmTypeConvention
Set the ExpandConfiguration
s of navigation properties of this structural type based on the ExpandAttribute
annotation on the class.
CountAttributeEdmPropertyConvention
Configures the $count
OData query options for specific columns with the CountAttribute
annotation. The $count
OData query option can be explicity enabled or disabled with the CountAttribute
annotation.
CountAttributeEdmTypeConvention
Set whether the $count
can be applied on the edm type. The $count
OData query option can be explicity enabled or disabled with the CountAttribute
annotation.
OrderByAttributeEdmTypeConvention
Configures the OData $orderby
query option settings for a type based on the OrderByAttribute
on the class or on the properties.
When used on a class, the default $orderby
value can be specified.
When used on properties it can also prevent that property from being referenced in an $orderby
OData query option.
FilterAttributeEdmTypeConvention
Configures the OData $filter
query option settings for a type based on the FilterAttribute
on the class or properties.
OrderByAttributeEdmPropertyConvention
Configures the OData $orderby
query option settings for a type based on the OrderByAttribute
on the class or on the properties.
When used on a class, the default $orderby
value can be specified.
When used on properties it can also prevent that property from being referenced in an $orderby
OData query option.
FilterAttributeEdmPropertyConvention
Configures the OData $filter
query option settings for a type based on the FilterAttribute
on the class or on the properties.
When used on a class, the default $filter
value can be specified.
When used on properties it can also prevent that property from being referenced in an $filter
OData query option.
SelectAttributeEdmTypeConvention
For classes that have SelectAttribute
, the attribute will list the properties that can be referenced by the $select
OData query option for this structural type.
SelectAttributeEdmPropertyConvention
Configures the OData $select
query option settings for a type based on the SelectAttribute
on the class or on the properties.
When used on a class, the default $select
value can be specified.
When used on properties it can also prevent that property from being referenced in an $select
OData query option.
SelfLinksGenerationConvention
Generates Item and Edit links in the OData annotations.
NavigationLinksGenerationConvention
Generate links without cast for declared and inherited navigation properties, or with a cast in derived types.
AssociationSetDiscoveryConvention
This convention adds an association set for each EDM navigation property defined in this type, its base types and all its derived types.
The target navigation source chosen is the default navigation source for the navigation property's target entity type.
The default navigation source for an entity type is the navigation source that contains entity of that entity type.
If more than one navigation source match, the default navigation source is none.
If no navigation sources match the default navigation source is the default navigation source of the base type.
ActionLinkGenerationConvention
calls action.HasActionLink(..) if the action binds to a single entity and has not previously been configured.
FunctionLinkGenerationConvention
calls function.HasFunctionLink(..) if the function binds to a single entity and has not previously been configured.
Interesting notes:
I tried to do some research on the history of NotFilterableAttribute
vs NonFilterableAttribute
but struggled to find a point of divergence in the open source libraries. Both of these attributes exist in the VS 2013 help docs and the System.Web.OData.Query
namespace. I assume at one point two different namespaces or libraries were merged together and the attributes were retained for backward compatibility.
What should have happened in the associated commit was that one of these attributes should have been deprecated (annotated with [Obsolete]
) and in a future version that deprecated class should have been removed, certainly long before now.
NotSortableAttribute
and UnsortableAttribute
...Some of these conventions have the same implementation in two different convention classes, one mapped to the Entity Type
, the other to the Property
. At first glance this looks redundant, but it is necessary for attributes that support both class and property annotation. The reason it is necessary is that the presence of the associated attribute triggers the convention to be evaluated at all. The OData conventions do not operate like the EF code first conventions that evaluate all types and properties for a match. The model is iterated, not the conventions. A class level attribute application, like PageAttribute
if we want to allow it to be specified on the property it still needs to apply the logic to the Edm Type. The reverse is try to for FilterAttribute
that can be declared once on the Edm Type with an array of properties, or you can manage the properties individually, you might even have both, with property level attributes to explicitly prevent $filter access.
Upvotes: 0
Reputation: 131
The best explanation I'm aware of, is here
Routing Conventions in ASP.NET Web API 2 Odata
NB this is Odata 3, not odata 4
Upvotes: 0
Reputation: 45283
From what I've seen so far, the conventions are those used by Entity Framework, as opposed to any new ones for OData. Please correct me if I am wrong.
More on Code-first conventions, below, but there are many more in the Julie Lerman book I have yet I cannot find an exhaustive list of them on the web.
http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx
Update
The EF modelling conventions system is pluggable and each convention is represented by a class encapsulating the behaviour, and those classes are listed here:
However that doesn't help with which ones are applicable or used by the ODataConventionModelBuilder
if any.
Upvotes: 3