Con*_*nko 6 asp.net asp.net-mvc asp.net-web-api
首先,这并不是几十个其他帖子的重复,我已经尝试了所有这些帖子,但没有一个是有效的.
我有一个模型,其中包含的内容比我的web api消费者需要的更多.
public class Publication
{
[Key]
public int PublicationID { get; set; }
public string PublicationTitle { get; set; }
public string Frequency { get; set; }
public DateTime NextIssueDate { get; set; }
public DateTime SpaceDeadline { get; set; }
public DateTime MaterialsDeadline { get; set; }
public DateTime CreatedDt { get; set; }
public string CreatedBy { get; set; }
public DateTime UpdatedDt { get; set; }
public string UpdatedBy { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我只想说一些要在API中传递的字段.我已经尝试过这段代码但是在Json结果中没有遗漏说UpdateBy,而是返回null值.我怎么摆脱它?我已经尝试了几十种变体,但它们要么无法编译,要么无法返回结果.
public IQueryable<Publication> GetPublications()
{
return db.Publications
.ToList()
.Select(p => new Publication {
PublicationID = p.PublicationID,
PublicationTitle = p.PublicationTitle,
Frequency = p.Frequency,
NextIssueDate = p.NextIssueDate
})
.AsQueryable();
}
Run Code Online (Sandbox Code Playgroud)
Sin*_*tic 10
不要序列化你的DAO.创建一个完整的合同,然后有选择地序列化它.要为不同的案例创建不同的合同,您可以使用Json.Net简化它; 你可以创建一个自定义合约解析器,并将其用作SerializeObject()的参数,就像这样
static void Main(string[] args)
{
var person = new TestContract {FirstName = "John", LastName = "Doe", Age = 36};
var firstNameContract = new SelectiveSerializer("firstname");
var allPropertiesContract = new SelectiveSerializer("firstname, lastname, age");
var allJson = JsonConvert.SerializeObject(
person,
Formatting.Indented,
new JsonSerializerSettings {ContractResolver = allPropertiesContract});
var firstNameJson = JsonConvert.SerializeObject(
person,
Formatting.Indented,
new JsonSerializerSettings {ContractResolver = firstNameContract});
Console.WriteLine(allJson);
// {
// "FirstName": "John",
// "LastName": "Doe",
// "Age": 36
// }
Console.WriteLine(firstNameJson);
// {
// "FirstName": "John",
// }
}
public class SelectiveSerializer : DefaultContractResolver
{
private readonly string[] _fields;
public SelectiveSerializer(string fields)
{
var fieldColl = fields.Split(',');
_fields = fieldColl
.Select(f => f.ToLower().Trim())
.ToArray();
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = o => _fields.Contains(member.Name.ToLower());
return property;
}
}
public class TestContract
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果没有太多努力,您可以将其用于默认的mediatype格式化程序(在管道中)以在请求中查找名为"fields"或其他的参数,然后使用自定义合约解析程序(如果存在),然后它将是无缝默认如果指定则限制字段的行为,如果未指定则序列化整个对象.
在学术方面,这是正当理由:对数据的任何修改都被视为"视图关注点",这意味着,在API中,它应该由查询参数控制并接受标题.在这种情况下,数据的"表示"是application/json,您选择"过滤"返回的字段.所有这些都可以(并且应该是,imo)在序列化期间处理.因此,在这种情况下,您的"模型"将始终是完整模型与模型的某个子集.此示例中的完整模型包含名字,姓氏和年龄.实际上,这可能是数百个属性.如果要允许客户端选择完整模型的子集,则可以使用选择性序列化来完成此操作.
你可以在图形apis中使用类似的行为.在那里,大型模型的默认设置是,如果您没有指定字段,则会获得一个空对象,从而迫使客户端对其要求的内容非常具体,这在有效负载大小很重要时很有用(例如移动应用程序).并且,没有什么能阻止创建像'name'这样的字段预设,这可能意味着'firstname,lastname'或'all'包含所有属性.
我从来不喜欢拥有数百个数据对象,这些数据对象都是为20个不同的上下文中使用的数据集提供一些特殊要求,其中某些情况需要更多数据而其他情况需要更少数据.IMO如果您必须通过相同的过程来获取数据,无论是否完成,您都不应该浪费时间创建额外的对象来为客户端构建数据框架,这应该可以帮助您实现这一目标.
这是因为您正在返回一组Publication对象,因此您将获得该类中包含的每个属性,无论您是否填充它.如果要返回属性的子集,则创建一个只包含要返回的属性的类,并在查询中创建该类的实例.
public IQueryable<WhatIReallyWantToReturn> GetPublications()
{
return db.Publications
.ToList()
.Select(p => new WhatIReallyWantToReturn {
PublicationID = p.PublicationID,
PublicationTitle = p.PublicationTitle,
Frequency = p.Frequency,
NextIssueDate = p.NextIssueDate
})
.AsQueryable();
}
private class WhatIReallyWantToReturn
{
public int PublicationID { get; set; }
public string PublicationTitle { get; set; }
public string Frequency { get; set; }
public DateTime NextIssueDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9603 次 |
| 最近记录: |