I have a controller like this:
using Microsoft.AspNetCore.Mvc;
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
}
[Route("api/[controller]")]
public class ValuesController : Controller {
[HttpGet]
public IActionResult Get() {
return new OkObjectResult(new[] {
new Person { FirstName = "John", LastName = "Doe" }
});
}
}
I would like to be able to specify the properties I want from the response in a asp.net core REST API.
For example, a GET
to api/values
should return an object with all its properties:
{
"FirstName":"John",
"LastName":"Doe"
}
While, a GET
to api/values?fields=FirstName
should return only the FirstName property:
{
"FirstName":"John"
}
I tried specifying a ContractResolver in my Startup class like this:
class QueryStringResolver : DefaultContractResolver {
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) {
HttpContextAccessor httpContextAccessor = new HttpContextAccessor();
string fieldsQuery = httpContextAccessor.HttpContext.Request.Query["fields"];
if (!string.IsNullOrEmpty(fieldsQuery)) {
var fields = from f in fieldsQuery.Split(",", StringSplitOptions.RemoveEmptyEntries) select f.Trim().ToLowerInvariant();
return base.CreateProperties(type, memberSerialization).Where(p => fields.Contains(p.PropertyName.ToLowerInvariant())).ToList();
} else {
return base.CreateProperties(type, memberSerialization);
}
}
}
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services
.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new QueryStringResolver();
});
}
// rest of Startup class omitted...
}
The problem is that the CreateProperties
method is invoked only at the first request, and not for each request.
Is there a way to specify which properties should be serialized at each request?
Please note that I don't want to change the Get method implementation or the returned class definition, I would just like to act on the serialization, so that I can re-use the same query string parameter in several methods.