为webapi模型中的对象指定唯一标识符属性

在对WebApi的POST调用中,我试图返回一个Created(newobject)的东西。 但是ApiController中没有Created的签名,它只能接受对象并完成剩下的工作。

如果我返回类似的东西,它工作正常:

return Created(newobject.blahid.ToString(), newobject); 

或者如果我做了

 return CreatedAtRoute("DefaultApi", new { controller = ControllerContext.ControllerDescriptor.ControllerName, id = newobject.blahid.ToString()}, newobject); 

我想简化这个:

 return Created(newobject); 

我需要在BaseController中实现一个方法

 public class BaseController : ApiController { protected new CreatedNegotiatedContentResult Created(T content) { var id = GetId(content);//need help here return base.Created(id, content); } } 

我不想担心在不同模型中以不同方式调用对象的唯一标识符,例如myobjguid,someblahguid等。我只想找到它并将其标记为“id”。

如果我的模型是

  public class Model_A { public List ChildModels { get; set; } [LookForThisAttribute]//I want something like this public Guid Model_AGuid { set; get; } public Guid ? ParentGuid { set; get; } public List OtherObjects { set; get; } } 

是否有一个属性([LookForThisAttribute])或我可以在我的所有模型上设置的东西,以指定如果我找到它,这是被认为是唯一标识符的人。

就像Entity Framework中的[Key]属性一样。 无论你怎么称呼它,Entity Framework都知道它将成为主键。

那么GetId(T内容)方法可以获取对象并返回具有[LookForThisAttribute]集的属性的值?

我最终编写了自己的Attribute,然后在BaseController中查找它。

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public sealed class UniqueIdAttribute: Attribute { } 

并在BaseController Created方法中:

  protected CreatedNegotiatedContentResult Created(T content) { var props =typeof(T).GetProperties().Where( prop => Attribute.IsDefined(prop, typeof(UniqueIdAttribute))); if (props.Count() == 0) { //log this return base.Created(Request.RequestUri.ToString(), content); } var id = props.FirstOrDefault().GetValue(content).ToString(); return base.Created(new Uri(Request.RequestUri + id), content); } 

Mark Gravell的post帮助我获取具有自定义属性的属性的值: 如何获取具有给定属性的属性列表?

与控制器的相应unit testing一起工作对我来说很好。

现在我可以调用Created(anyobject); 来自所有ApiControllers,只要他们使用我的自定义属性装饰它们,就不用担心人们为他们的ID添加的不同名称。