【发布时间】:2018-11-13 21:47:43
【问题描述】:
我有一个这样的控制器:
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" }
});
}
}
我希望能够从 asp.net 核心 REST API 的响应中指定我想要的属性。
例如,GET 到 api/values 应该返回一个包含所有属性的对象:
{
"FirstName":"John",
"LastName":"Doe"
}
虽然,GET 到 api/values?fields=FirstName 应该只返回 FirstName 属性:
{
"FirstName":"John"
}
我尝试在我的 Startup 类中指定一个 ContractResolver,如下所示:
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...
}
问题在于CreateProperties 方法仅在第一个请求时调用,而不是针对每个请求。
有没有办法指定在每个请求中应该序列化哪些属性?
请注意,我不想更改 Get 方法的实现或返回的类定义,我只想对序列化进行操作,以便可以重复使用相同的查询几种方法中的字符串参数。
【问题讨论】:
-
条件属性序列化意味着为我的每个对象的每个属性添加一个 ShouldSerializeXXX 方法。
-
在这个例子中很好,但我宁愿在真正的 API 中避免这种情况。
-
@PaoloTedesco 你的问题是你在哪里实例化了
QueryStringResolver。你在StartUp上做了它,当你需要它时,根据你想要的结果启动它。你把它放在哪里是有道理的,但你解释的行为表明你利用资源太远了。尝试先在 APIController 上使用QueryStringResolver,然后一次将其提升一级。
标签: c# asp.net-core