I have an endpoint that I am migrating. The current format of the JSON being sent to the endpoint is:
{
"settings":{
"Target":30,
"UserId":12345
}
}
Currently with a method signature like this...
public string GetTarget(Settings settings);
It appears that the Web API deserializer is looking for the JSON to be formatted as follows (with no top level variable name):
{
"Target":30,
"UserId":12345
}
I have a legacy app that sends the JSON with the "settings" variable name and I cannot update it to send the unnested format. Is there any way to have Web API target the nested properties within "settings"?
CodePudding user response:
You can try to use custom model binding.Here is a demo:
Settings:
public class Settings {
public int Target { get; set; }
public int UserId { get; set; }
}
action:
public string GetTarget([ModelBinder(BinderType = typeof(CustomBinder))] Settings settings)
CustomBinder:
public class CustomBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model = new Settings();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);
model = JsonConvert.DeserializeObject<Settings>(mydata["settings"].ToString());
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
CodePudding user response:
try this,it was tested using VS and Postman. It doesn't need any custom converter
using Newtonsoft.Json.Linq;
....
public string GetTarget([FromBody] JObject settingsObj)
{
Settings settings;
if (settingsObj["settings"] != null) settings = settingsObj["settings"].ToObject<Settings>();
else settings = settingsObj.ToObject<Settings>();
......
}
public class Settings
{
public int Target { get; set; }
public int UserId { get; set; }
}