2

Closed

XElement is not working with DefaultBodyModelValidator

description

The scenario broken is that if defining XElement property in odata entity type, POST or PUT the entity will result in failure. The error message is:

PUT http://localhost:83/911518e0-e801-48db-9eff-d513a6ca82f3/Resources(R1) HTTP/1.1
Host: localhost:83
Accept: application/json; odata=minimalmetadata
Content-Type: application/json; odata=minimalmetadata
Content-Length: 143

{
"Name":"R1",
"InstrinsicSettings":"<VMTier instances=\"3\">\r\n <MoreSettings />\r\n</VMTier>"
}

[From the trace log...]
Operation=JQueryMvcFormUrlEncodedFormatter.GetPerRequestFormatterInstance
WebApiTest.vshost.exe Information: 0 : Message='Value read='WebApiTest.Resource'', Operation=ODataMediaTypeFormatter.ReadFromStreamAsync
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
WebApiTest.vshost.exe Error: 0 : Operation=HttpActionBinding.ExecuteBindingAsync, Exception=System.ArgumentException: An item with the same key has already been added.
   mscorlib.dll!System.ThrowHelper.ThrowArgumentException(System.ExceptionResource resource) Line 74 + 0x2f bytes    C#
  mscorlib.dll!System.Collections.Generic.Dictionary<string,System.Web.Http.Metadata.Providers.AssociatedMetadataProvider<System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadata>.PropertyInformation>.Insert(string key, System.Web.Http.Metadata.Providers.AssociatedMetadataProvider<System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadata>.PropertyInformation value, bool add) Line 329 + 0xa bytes    C#
  mscorlib.dll!System.Collections.Generic.Dictionary<System.__Canon,System.__Canon>.Add(System.__Canon key, System.__Canon value) Line 185 + 0xb bytes C#
   System.Web.Http.dll!System.Web.Http.Metadata.Providers.AssociatedMetadataProvider<System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadata>.CreateTypeInformation(System.Type type) + 0x26e bytes  
   System.Web.Http.dll!System.Web.Http.Metadata.Providers.AssociatedMetadataProvider<System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadata>.GetTypeInformation(System.Type type) + 0x5b bytes   
   System.Web.Http.dll!System.Web.Http.Metadata.Providers.AssociatedMetadataProvider<System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadata>.GetMetadataForPropertiesImpl.MoveNext() + 0x111 bytes 
   System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata metadata, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext) + 0x152 bytes   
   System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata metadata, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext, object container) + 0x11b bytes   
   System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata metadata, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext) + 0x13b bytes   
   System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata metadata, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext, object container) + 0x11b bytes   
  System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.Validate(object model, System.Type type, System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, System.Web.Http.Controllers.HttpActionContext actionContext, string keyPrefix) + 0x29c bytes    
   System.Web.Http.dll!System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync.AnonymousMethod__0(object model) + 0xb8 bytes  
  System.Web.Http.dll!System.Threading.Tasks.TaskHelpersExtensions.Then<object>.AnonymousMethod__35() + 0x49 bytes  
   System.Web.Http.dll!System.Threading.Tasks.TaskHelpersExtensions.ToAsyncVoidTask.AnonymousMethod__48() + 0x23 bytes  
   System.Web.Http.dll!System.Threading.Tasks.TaskHelpers.RunSynchronously<System.Threading.Tasks.TaskHelpersExtensions.AsyncVoid>(System.Func<System.Threading.Tasks.Task<System.Threading.Tasks.TaskHelpersExtensions.AsyncVoid>> func, System.Threading.CancellationToken cancellationToken) + 0x64 bytes   
  System.Web.Http.dll!System.Threading.Tasks.TaskHelpersExtensions.ToAsyncVoidTask(System.Action action) + 0x87 bytes 
   System.Web.Http.dll!System.Threading.Tasks.TaskHelpersExtensions.Then<object>.AnonymousMethod__34(System.Threading.Tasks.Task<object> t) + 0xba bytes      
   System.Web.Http.dll!System.Threading.Tasks.TaskHelpersExtensions.ThenImpl<System.Threading.Tasks.Task<object>,System.Threading.Tasks.TaskHelpersExtensions.AsyncVoid>(System.Threading.Tasks.Task<object> task, System.Func<System.Threading.Tasks.Task<object>,System.Threading.Tasks.Task<System.Threading.Tasks.TaskHelpersExtensions.AsyncVoid>> continuation, System.Threading.CancellationToken cancellationToken, bool runSynchronously) + 0xf2 bytes       
   System.Web.Http.dll!System.Threading.Tasks.TaskHelpersExtensions.Then<object>(System.Threading.Tasks.Task<object> task, System.Action<object> continuation, System.Threading.CancellationToken cancellationToken, bool runSynchronously) + 0xfb bytes    
   System.Web.Http.dll!System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) + 0x193 bytes  
   System.Web.Http.OData.dll!System.Web.Http.OData.PerRequestParameterBinding.ExecuteBindingAsync(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Line 49 + 0x16 bytes C#
   System.Web.Http.dll!System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync.AnonymousMethod__0(System.Web.Http.Controllers.HttpParameterBinding parameterBinder) + 0x4a bytes     

The problem here is because XElement has its own type descriptor which will add additional property descriptors together with reflection based property descriptors. Unfortunately, there are some descriptors having duplicate names, like Value property.

Per HongMei: The bug is in the MediaTypeFormatterCollection.IsTypeExcludedFromValidation() where we were exclude things like JObject and xmlNode from validation, and we should add XElement in the list.
Closed Jun 6, 2013 at 6:28 PM by kichalla
Verified.