WebApi icon indicating copy to clipboard operation
WebApi copied to clipboard

Confusing format of Metadata

Open komdil opened this issue 3 years ago • 2 comments

I am getting metadata in JSON format, But there are $ characters and properties that are not a collection. Also, I want add new attributes and it is not in the same format

Assemblies affected

Microsoft.AspNetCore.OData 7.5.12

First confusing:

Reproduce steps

Get meta data in JSON format using: https://localhost:44383/odata/$metadata?$format=json

Expected result

I would expect metadata without $ character and properties are listed:

"Student": {
            "Kind": "EntityType",
            "Key": [
                "Id"
            ],
            "Properties": [
				"Id": {
					"Type": "Edm.Guid"
				},
				"Name": {
					"Nullable": true
				},
				"Score": {
					"Type": "Edm.Int32"
				},
				"Backpacks": {
					"Kind": "NavigationProperty",
					"Collection": true,
					"Type": "ODataCoreTest.Backpack"
				}
		    ]
        },

Actual result

Metadata format of an entity like this:

"Student": {
            "$Kind": "EntityType",
            "$Key": [
                "Id"
            ],
            "Id": {
                "$Type": "Edm.Guid"
            },
            "Name": {
                "$Nullable": true
            },
            "Score": {
                "$Type": "Edm.Int32"
            },
            "Backpacks": {
                "$Kind": "NavigationProperty",
                "$Collection": true,
                "$Type": "ODataCoreTest.Backpack"
            }
        },

Second confusing:

Reproduce steps

I want to add my custom attribute in the entity, for example, Label. I have the following methods to do this:

 static void SetAttribute(string entityName, string attributeName, string stringValue, IEdmModel edmModel)
        {
            var entityType = edmModel.EntityContainer.FindEntitySet(entityName)?.EntityType();
            var stringType = EdmCoreModel.Instance.GetString(true);
            var value = new EdmStringConstant(stringType, stringValue);
            edmModel.SetAnnotationValue(entityType, string.Empty, attributeName, value);
        }

And usage:

SetAttribute("Student", "Label", "Student entity", model);

Get meta data in JSON format using: https://localhost:44383/odata/$metadata?$format=json

Expected result

The label is not with $ character

Actual result

The label will be shown, but it is not with $ character as $Kind, $BaseType, ... I can add Label with $ like : SetAttribute("Student", "$Label", "Student entity", model);, it will show label with $ in JSON format, but will throw exception on xml version:

An unhandled exception has occurred while executing the request.
System.ArgumentException: Invalid name character in '$Label'. The '$' character, hexadecimal value 0x24, cannot be included in a name.
   at System.Xml.XmlWellFormedWriter.CheckNCName(String ncname)
   at System.Xml.XmlWellFormedWriter.WriteStartAttribute(String prefix, String localName, String namespaceName)
   at System.Xml.XmlAsyncCheckWriter.WriteStartAttribute(String prefix, String localName, String ns)
   at System.Xml.XmlWriter.WriteAttributeString(String localName, String ns, String value)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSchemaXmlWriter.WriteAnnotationStringAttribute(IEdmDirectValueAnnotation annotation)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.VisitAttributeAnnotations(IEnumerable`1 annotations)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.ProcessEntityType(IEdmEntityType element)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitSchemaType(IEdmType definition)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitSchemaElement(IEdmSchemaElement element)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitCollection[T](IEnumerable`1 collection, Action`1 visitMethod)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitSchemaElements(IEnumerable`1 elements)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.VisitEdmSchema(EdmSchema element, IEnumerable`1 mappings)

Additional detail

It is not a big problem, but it will be good make this consistent

komdil avatar Nov 30 '21 03:11 komdil

The json property names "$Kind", "$Key", "$Type", "$Nullable", "$Collection" are meta level properties as defined by the OData standard similar to keywords in a programing language. To avoid conflicts between model level JSON property names vs meta level JSON property names the standard decided that the CSDL JSON standard uses the $ prefix and does not allow to use property names starting with $ (hence the error message)

This is expected behavior and in conformance with the standard. Please reach out if you want to discuss further.

chrisspre avatar Nov 30 '21 17:11 chrisspre

The interesting issue is that it appears legal to create an attribute with the "$" prefix in the JSON metadata. We should not be able to create a name in one format that's not legal in the other format.

mikepizzo avatar Mar 14 '22 20:03 mikepizzo