We are creating RestService with Asp.Net WebApi. But for some reason Name
property is ignored in DataMember
attribute when trying to deserialize complex property with [FromURI]
attribute.
For example we might have: Method:
public IHttpActionResult Get([FromUri]User user)
Model:
[DataContract]
public class User
{
[DataMember(Name = "username")]
public string Username{ get; set; }
[DataMember(Name = "isActive", IsRequired = false)]
public bool? Active { get; set; }
}
When deserializing user
we get username as expected, but null
for Active
. On the other hand when serializing data we get both isActive
and username
as expected. If we send request with active
in query string it works as expected.
It's obviously problem with IModelBinder
. It doesn't use DataMember
's Name
property for some reason. I checked what formaters are included and 4 default ones are registered:
System.Net.Http.Formatting.JsonMediaTypeFormatter
System.Net.Http.Formatting.XmlMediaTypeFormatter
System.Net.Http.Formatting.FormUrlEncodedMediaTypeFormatter
System.Net.Http.Formatting.JQueryMvcFormUrlEncodedFormatter
I don't have a way to check which one is used on request. I would assume that its FormUrlEncodedMediaTypeFormatter
but I can't be sure. Also, I am not sure if it even supports Name
property.
I already checked for a solution and closest topic I could find was WebAPI DataMember Name not used when de/serializing via application/x-www-form-urlencoded but it doesn't use [FromUri]
but application/x-www-form-urlencoded
property and it wasn't really solved.
Any ideas, pointers or suggestions would be much appreciated.
The [FromUri] attribute is prefixed to the parameter to specify that the value should be read from the URI of the request, and the [FromBody] attribute is used to specify that the value should be read from the body of the request.
When the ASP.NET Web API calls a method on a controller, it must set values for the parameters, a process called parameter binding. In order to bind a model (an action parameter), that would normally default to a formatter, from the URI we need to decorate it with [FromUri] attribute.
Use [FromQuery]
instead other attributes.
And model for your request
http://localhost:8080/api/users?username=John&isActive=true
[Route("api/users")]
public class UsersController : Controller
{
[HttpGet]
public IHttpActionResult Get(User user)
{
//...
}
}
Will looks like
public class User
{
[FromQuery(Name = "username")]
public string Username{ get; set; }
[FromQuery(Name = "isActive")]
public bool? Active { get; set; }
}
Anyway best practice is to keep names in model as it parameters names in query.
In this case you dont have to provide "Name" parameter, only keep [FromQuery]
on queryClass, and lower casing .Net provide automaticly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With