locked
October 2011 CTP - Type Inheritance for properties of Complex Types RRS feed

  • Question

  • Hi!

    I am developping a custom data service that exposes data from a custom data access framework.

    Right now, I got stuck with a serialization problem when exposing a property of a complex type that has two child types:

     

    Lets say I have an Entity of type Document that has a complex property called MainRendition of type Rendition. Then, Rendition has two child types: UrlRendition and FileRendition.

     

    When I try to query the Document set, if one of the returned instances has property MainRendition assigned with an object of type UrlRendition I get the following exception:

    <m:error>
    	<m:code />
    	<m:message xml:lang="pt-PT">An error occurred while processing this request.</m:message>
    	<m:innererror>
    		<m:message>
    			A value was encountered that has a type name that is incompatible with the metadata. The value specifies its type as 'Fbx.Domain.Model.Doc.UrlRendition', but the type specified in the metadata is 'Fbx.Domain.Model.Doc.Rendition'.
    		</m:message>
    		<m:type>Microsoft.Data.OData.ODataException</m:type>
    		<m:stacktrace>at Microsoft.Data.OData.WriterValidationUtils.ValidateMetadataType(IEdmTypeReference typeReferenceFromMetadata, IEdmTypeReference typeReferenceFromValue)&#xD;
    		   at Microsoft.Data.OData.WriterValidationUtils.ResolveTypeNameForWriting(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata, String&amp; typeName, EdmTypeKind typeKind, Boolean isOpenPropertyType)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriterUtils.WriteComplexValue(XmlWriter writer, IEdmModel model, ODataComplexValue complexValue, IEdmTypeReference metadataTypeReference, Boolean isOpenPropertyType, Boolean isWritingCollection, Boolean isWritingResponse, ODataWriterBehavior writerBehavior, Action`1 beforeValueAction, Action`1 afterValueAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, String multiValueItemTypeName, ODataVersion version, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriterUtils.WriteProperty(XmlWriter writer, IEdmModel model, ODataProperty property, IEdmStructuredType owningType, ODataVersion version, Boolean isTopLevel, Boolean isWritingCollection, Boolean isWritingResponse, ODataWriterBehavior writerBehavior, Action`1 beforePropertyAction, EpmValueCache epmValueCache, EpmSourcePathSegment epmParentSourcePathSegment, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriterUtils.WriteProperties(XmlWriter writer, IEdmModel model, IEdmStructuredType owningType, IEnumerable`1 cachedProperties, ODataVersion version, Boolean isWritingCollection, Boolean isWritingResponse, ODataWriterBehavior writerBehavior, Action`1 beforePropertiesAction, Action`1 afterPropertiesAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriterUtils.WriteComplexValue(XmlWriter writer, IEdmModel model, ODataComplexValue complexValue, IEdmTypeReference metadataTypeReference, Boolean isOpenPropertyType, Boolean isWritingCollection, Boolean isWritingResponse, ODataWriterBehavior writerBehavior, Action`1 beforeValueAction, Action`1 afterValueAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, String multiValueItemTypeName, ODataVersion version, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriterUtils.WriteProperty(XmlWriter writer, IEdmModel model, ODataProperty property, IEdmStructuredType owningType, ODataVersion version, Boolean isTopLevel, Boolean isWritingCollection, Boolean isWritingResponse, ODataWriterBehavior writerBehavior, Action`1 beforePropertyAction, EpmValueCache epmValueCache, EpmSourcePathSegment epmParentSourcePathSegment, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriterUtils.WriteProperties(XmlWriter writer, IEdmModel model, IEdmStructuredType owningType, IEnumerable`1 cachedProperties, ODataVersion version, Boolean isWritingCollection, Boolean isWritingResponse, ODataWriterBehavior writerBehavior, Action`1 beforePropertiesAction, Action`1 afterPropertiesAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriter.WriteEntryContent(ODataEntry entry, IEdmEntityType entryType, EntryPropertiesValueCache propertiesValueCache, EpmSourcePathSegment rootSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)&#xD;
    		   at Microsoft.Data.OData.Atom.ODataAtomWriter.EndEntry(ODataEntry entry)&#xD;
    		   at Microsoft.Data.OData.ODataWriterCore.&lt;WriteEndImplementation&gt;b__18()&#xD;
    		   at Microsoft.Data.OData.ODataWriterCore.InterceptException(Action action)&#xD;
    		   at Microsoft.Data.OData.ODataWriterCore.WriteEndImplementation()&#xD;
    		   at Microsoft.Data.OData.ODataWriterCore.WriteEnd()&#xD;
    		   at System.Data.Services.Serializers.EntitySerializer.WriteEntry(IExpandedResult expanded, Object element, ResourceType expectedType)&#xD;
    		   at System.Data.Services.Serializers.EntitySerializer.WriteFeedElements(IExpandedResult expanded, IEnumerator elements, ResourceType expectedType, String title, Uri relativeUri, Uri absoluteUri, Boolean hasMoved, Boolean topLevel)&#xD;
    		   at System.Data.Services.Serializers.EntitySerializer.WriteTopLevelElements(IExpandedResult expanded, IEnumerator elements, Boolean hasMoved)&#xD;
    		   at System.Data.Services.Serializers.Serializer.WriteRequest(IEnumerator queryResults, Boolean hasMoved)&#xD;
    		   at System.Data.Services.ResponseBodyWriter.Write(Stream stream)
    		</m:stacktrace>
    	</m:innererror>
    </m:error>
    


    *This happens for both atom and json serializers, and also with the built-in ReflectionServiceProvider.

    **The problem seems to be in method WriterValidationUtils.ValidateMetadataType(...) of Microsoft.Data.OData.dll

    *** This issue is also present in March 2011 CTP2 release, but strangely it only occurs for Multivalue Complex Properties

    Is there any workaround this issue for now? Or will a new release be available soon?

     

    Best regards,

    João

     

    Friday, January 27, 2012 2:50 PM

Answers

  • Hi,

    Type inheritance for entity types is totally supported. In fact in V3 it's getting much better since properties on derived types are now fully supported in the query itself.

    Type inheritance for complex types is not supported. It actually never really worked even in V2.

    Thanks,


    Vitek Karas [MSFT]
    Saturday, January 28, 2012 7:46 PM
    Moderator

All replies

  • Hi ,

    Did yu try to use  KnowType attribute ?

     

    [DataContract]
    [KnownType(
    typeof(ClassChild1))]
    [KnownType(
    typeof(ClassChild2))]

     

    best regards,


    So B
    Friday, January 27, 2012 4:08 PM
  • Hi,

    Complex type inheritance is not supported. It's been partially enabled by accident and as such is pretty broken. So please don't use it.

    Thanks,


    Vitek Karas [MSFT]
    Friday, January 27, 2012 4:45 PM
    Moderator
  • Hi Vitek,

    Altough this feature is now broken, it won't be dropped right?

    I think type inheritance is clearly a must have in OData for either Complex and Entity types.

     

    Thanks,

    João Ribeiro

    Friday, January 27, 2012 6:27 PM
  • Hi,

    Type inheritance for entity types is totally supported. In fact in V3 it's getting much better since properties on derived types are now fully supported in the query itself.

    Type inheritance for complex types is not supported. It actually never really worked even in V2.

    Thanks,


    Vitek Karas [MSFT]
    Saturday, January 28, 2012 7:46 PM
    Moderator
  • Hi Vitek,

    Now that you have Entity Types inheritance support, why not extending the feature for complex types?

    The CSDL Format specification states that the EDM supports Entity Type and Complex Type inheritance, so I guess this limitation might be some implementation issue.

    It seems to me that you have already had most of the work supporting Entity Inheritance, why not going the last mile?

     

    Regards,

    João Ribeiro

     

     

    Monday, January 30, 2012 5:35 PM
  • Hi,

    It's a scoping decision. It's suprisingly not similar to entity type inheritance inside the implementation (for various good reasons, just imagine the list of features which would have to support this: writing, reading, metadata, query, URL query language, code-gen, client LINQ provider, ...). And we don't get many people asking for it.

    Since you're one :-) please vote for this feature here: http://blogs.msdn.com/b/astoriateam/archive/2010/09/10/what-do-you-want-to-see-added-changed-in-wcf-data-services.aspx

    Thanks,


    Vitek Karas [MSFT]
    Tuesday, January 31, 2012 9:59 AM
    Moderator
  • Hi,

    I already added this feature to the list. Anyone feel free to vote for it.

    I understand that this might be not easy to implement for the built-in data service, but just the support for it in the custom implementation support could increase OData adoption and value.

     

    Best regards,

    João Ribeiro

    Tuesday, January 31, 2012 2:49 PM