开发REST Api时,处理对象级元数据,CreatedBy,CreatedOn,ModifiedBy,ModifiedOn等的最佳方法是什么?
典型的课程可能是:
public class Person {
public Guid Id {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public DateTime CreatedOn {get; set}
public Guid CreatedBy {get; set;}
}
我曾经认为在理想世界中,REST http方法将直接映射到控制器方法,例如:
public void Post (Person person) {
...perform the logic to add a person.
}
因此,API的消费者理论上可以发布:
{
"Id": "...guid...",
"FirstName": "Joe",
"LastName" : "Bloggs",
"CreatedOn" : "01/01/12",
"CreatedBy" : "...guid..."
}
然而,它并不适合消费者设置Id,CreatedOn和CreatedBy。我不认为消费者有责任这样做。所以这会让我在我的Post
方法中做到:
public void Post (Person person) {
person.Id = Guid.NewGuid();
person.CreatedOn = DateTime.Now;
person.CreatedBy = ...get user credentials from request...
}
因此消费者可以自由发布:
{
"FirstName": "Joe",
"LastName" : "Bloggs"
}
如果我们想使用Put方法进行更新怎么办?好吧,这给我们带来了同样的问题,如果我不想(或不相信)消费者传递这个元数据,那么我就不得不在我的Put
方法中做到这一点:
public void Put (Person person) {
Person existingPerson = myRepository.GetEmployee(person.Id);
existingPerson.FirstName = person.FirstName;
existingPerson.LastName = person.LastName;
myRepository.Save(existingEmployee);
}
我开始怀疑将消费者json / xml反序列化为模型对象并通过Post (Person person
或Put (Person person)
是否真的有意义,因为我从中获得了最微薄的好处它。为什么不将所有内容反序列化为一个字典(虽然只对json真的可行)?
我是否遗漏了一些关于REST的基本知识?将Id和1属性反序列化为模型对象,然后检索完整对象并更新它是否正常?我是否应该强迫我的消费者每次都通过所有内容然后验证它?
我喜欢消费者通过一大块json或xml的想法,当它到达我的控制器时,我只是处理一个对象。这看起来有点乱,所有这些忽略属性和预先获取更新等现有记录除非我从根本上误解REST?
答案 0 :(得分:1)
在我看来,您正在考虑的设计选项并非特定于REST,但一般适用于服务设计。我读这个的方式,基本问题似乎是谁负责填充这些字段,调用者或服务的业务逻辑?
对于我的两分钱,我认为作为服务器的责任有两个原因。首要的是 - 安全。客户端脚本本质上是不安全的,因此不应该被信任。例如,有动力的个人可以轻易伪造您的审计跟踪并使其看起来好像另一个用户执行了该操作。其次,我将audit / id字段的填充视为交叉切割被调用方法的实际业务目的的逻辑。为了创建一个人,客户端不应该知道如何表示id的实现细节。
至于使用字典与模型,我认为这是个人偏好。这两种方法都不会强制客户端传递完整的字段集。两者都支持一种设计,其中客户端仅传递操作的主要字段集。物化到模型或字典中只会遗漏您的审计/ ID字段。同样,这两种方法都不需要验证服务器端的只读字段,因为无法保证客户端不会更改它们。