0

In a POST call to a WebApi I am trying to return a Created(newobject) thing. But there is no signature for Created in ApiController that can only take the object and do the rest.

It works fine if I return something like:

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

or if I do a

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

I want to simplify this to:

return Created(newobject);

I would need to implement a method in a BaseController

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

I don't want to worry about the Unique Identifier for an object being called differently in different models e.g. myobjguid, someblahguid etc. I would just want to find it out and mark it as "id".

say if my model is

 public class Model_A
{
    public List<Model_A> ChildModels { get; set; }

    [LookForThisAttribute]//I want something like this
    public Guid Model_AGuid { set; get; }

    public Guid ? ParentGuid { set; get; }

    public List<SomeOtherObject> OtherObjects { set; get; }
}

Is there an attribute([LookForThisAttribute]) or something I can set on all my models to specify that this is the guy to be assumed as THE unique identifier if I ever look for it.

Just like the [Key] attribute in Entity Framework. No matter what you call it, Entity Framework know its going to be the primary key.

So the GetId(T content) method can take the object and return the value of the property that has a [LookForThisAttribute] set?

Abhishek Tiwari
  • 417
  • 3
  • 14

1 Answers1

0

I ended up writing my own Attribute and then looking up for it in the BaseController.

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

And in the BaseController Created method:

    protected CreatedNegotiatedContentResult<T> Created<T>(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's post here helped me with getting the value of the property that has my custom attribute: How to get a list of properties with a given attribute?

Along with a corresponding unit test for the controllers works fine for me.

Now I can just call Created(anyobject); from all ApiControllers without bothering about the different names people put for their IDs as long as they decorate it with my custom attribute.

Community
  • 1
  • 1
Abhishek Tiwari
  • 417
  • 3
  • 14