My Error is that the controller is not able to map the value; I have this situation that explains how to replicate the error:
public class FooA {
public string Property1 { set; get; }
public virtual string Property2 { set; get; }
}
public class FooB : FooA {
public new string Property2 { set; get; }
public string Property3 { set; get; }
}
As you know, the property Property2 is common for both classes, thereby when you are using in any controller this action:
public async task<string> ActionA([FromBody] FooA fooA)
{
return string.Empty;
}
// The error is thrown in this unwrapping.
public async task<string> ActionB([FromBody] FooB fooB)
{
return string.Empty;
}
The payload for FooA is of the request is:
{
"Property1" : "abc",
"Property2" : "def"
}
The payload for FooB is of the request is:
{
"Property2" : "abc",
"Property3" : "def"
}
This Exception will be thrown:
System.InvalidOperationException: The JSON property name for 'FooB' collides with another property.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(JsonClassInfo jsonClassInfo, JsonPropertyInfo jsonPropertyInfo)
at System.Text.Json.JsonClassInfo..ctor(Type type, JsonSerializerOptions options)
I have added Attributes such as [JsonIgnore]
but it fails with a payload like the first one.
or :
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
});
But it has not possible, my idea is to be SOLID and avoid to change the entire solution. It means Open Extensions (it means that extensions will solve future issues ) Closed to (already implemented) changes.
Do you have a particular setting in the AddJsonOptions to allow that conflicts by inheritences will be autoresolved using the child class always?
Notes 01: Even, when it is added the virtual ans new reserver keyword the controller throws the same exceptions.
you have to fix the classes, you have 2 choices
the common one
public class FooA
{
public string Property1 { set; get; }
public virtual string Property2 { set; get; }
}
public class FooB : FooA
{
public override string Property2 { set; get; }
public string Property3 { set; get; }
}
or if you want to have an access to 2 properties
public class FooA
{
public string Property1 { set; get; }
public string Property2 { set; get; }
}
public class FooB : FooA
{
public new string Property2 { set; get; }
public string Property3 { set; get; }
}
test
var json = @"{
""Property2"" : ""abc"",
""Property3"" : ""def""
}";
var jsonDeserialized=System.Text.Json.JsonSerializer.Deserialize<FooB>(json);
test reslut (in a json format)
{
"Property2": "abc",
"Property3": "def",
"Property1": null
}
but I recommend you to install Newtonsoft.Json serializer just config it in startup
using Newtonsoft.Json.Serialization;
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());
or if you use just controllers
services.AddControllers()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());