public override object Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext) { HttpActionDescriptor actionDescriptor = readContext.Request.GetActionDescriptor(); if (actionDescriptor != null && !actionDescriptor.GetCustomAttributes <ActionAttribute>().Any() && !actionDescriptor.GetCustomAttributes <CreateAttribute>().Any() && !actionDescriptor.GetCustomAttributes <UpdateAttribute>().Any() && !actionDescriptor.GetCustomAttributes <PartialUpdateAttribute>().Any()) { throw new InvalidOperationException($"{nameof(DefaultODataActionCreateUpdateParameterDeserializer)} is designed for odata actions|creates|updates|partialUpdates only"); } TypeInfo typeInfo = type.GetTypeInfo(); IDependencyResolver dependencyResolver = readContext.Request.GetOwinContext() .GetDependencyResolver(); ITimeZoneManager timeZoneManager = dependencyResolver.Resolve <ITimeZoneManager>(); JToken requestJsonBody = (JToken)readContext.Request.Properties["ContentStreamAsJson"]; using (JsonReader requestJsonReader = requestJsonBody.CreateReader()) { void Error(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e) { if (e.ErrorContext.Error is JsonSerializationException && e.ErrorContext.Error.Message.StartsWith("Could not find member ", StringComparison.InvariantCultureIgnoreCase)) { if (e.CurrentObject is IOpenType openDto) { openDto.Properties = openDto.Properties ?? new Dictionary <string, object>(); if (requestJsonReader.Read()) { openDto.Properties.Add((string)e.ErrorContext.Member, requestJsonReader.Value); } } e.ErrorContext.Handled = true; } if (e.ErrorContext.Handled == false) { readContext.Request.Properties["Request_Body_Json_Parse_Error"] = e.ErrorContext.Error; // This code is being executed in a try/catch which is located in ODataMediaTypeFormatter. That class will return defaul value (null) to actions which results into NRE in most cases. } } JsonSerializerSettings settings = DefaultJsonContentFormatter.DeSerializeSettings(); settings.Converters = new JsonConverter[] { _odataJsonDeserializerEnumConverter, _stringCorrectorsConverters, new ODataJsonDeSerializerDateTimeOffsetTimeZone(timeZoneManager) }; settings.MissingMemberHandling = MissingMemberHandling.Error; JsonSerializer deserilizer = JsonSerializer.Create(settings); deserilizer.Error += Error; try { object result = null; if (!typeof(Delta).GetTypeInfo().IsAssignableFrom(typeInfo)) { result = deserilizer.Deserialize(requestJsonReader, typeInfo); } else { List <string> changedPropNames = new List <string>(); using (JsonReader jsonReaderForGettingSchema = requestJsonBody.CreateReader()) { while (jsonReaderForGettingSchema.Read()) { if (jsonReaderForGettingSchema.Value != null && jsonReaderForGettingSchema.TokenType == JsonToken.PropertyName) { changedPropNames.Add(jsonReaderForGettingSchema.Value.ToString()); } } } TypeInfo dtoType = typeInfo.GetGenericArguments().ExtendedSingle("Finding dto type from delta").GetTypeInfo(); object modifiedDto = deserilizer.Deserialize(requestJsonReader, dtoType); Delta delta = (Delta)Activator.CreateInstance(typeInfo); if (modifiedDto is IOpenType openTypeDto && openTypeDto.Properties?.Any() == true) { delta.TrySetPropertyValue(nameof(IOpenType.Properties), openTypeDto); } foreach (string changedProp in changedPropNames.Where(p => p != nameof(IOpenType.Properties) && dtoType.GetProperty(p) != null)) { delta.TrySetPropertyValue(changedProp, dtoType.GetProperty(changedProp).GetValue(modifiedDto)); } result = delta; } return(result); } finally { deserilizer.Error -= Error; } } }