1
votes

I'm quite familiar with MVC, but fairly new to WebAPI and I've run into a confusing issue.

I have a controller (Which inherits from ApiController) called "DummyController" and it's got the 5 default scaffolded methods for get,post,put and delete (2 for get), and I've addd my own method at the bottom called "FindDummyObjects()" which I've decorated with the [HttpGet] attribute.

when I navigate to "api/dummy" or "api/dummy/get", I get the default result fo the 2 string objects ("value1" and "value2"). However, when I navigate to "api/dummy/FindDummyObjects", it complains that "The parameters dictionary contains a null entry for parameter 'id'".

This means that it's not pointing to my Action at all (As it is parameterless), so it's probably pointing to the default "Get(int id)" action.

When I comment out all actions except my own, I get the results I expect.

So my question is this, with WebAPI, is it only possible to have 1 action per http verb with a certain set of parameters, regardless of whether the action's names differ?

For example, it seems as though it will not be possible for me to 10 different http GET actions in a single controller, unless they all have different parameters and use the action name "Get" (Unless I do some custom routing I suppose).

Is that correct?

Code: // GET api/dummy public IEnumerable Get() { return new string[] { "value1", "value2" }; }

    // GET api/dummy/5
    public string Get(int id)
    {
        return "value";
    }

    // POST api/dummy
    public void Post([FromBody]string value)
    {
    }

    // PUT api/dummy/5
    public void Put(int id, [FromBody]string value)
    {
    }

    // DELETE api/dummy/5
    public void Delete(int id)
    {
    }

    [HttpGet]
    public IEnumerable<Models.DummyObject> FindDummyObjects()
    {
        IList<Models.DummyObject> myDummyList = new List<Models.DummyObject>();

        for (int i = 0; i < 10; i++)
        {
            Models.DummyObject dumObj = new Models.DummyObject();
            dumObj.ObjectId = i;
            dumObj.ObjectName = string.Empty;

            myDummyList.Add(dumObj);
        }

        return myDummyList;
    }
1
This doesn't sound like correct behavior. If the names of the actions differ, then they're entirely different routes and the framework should easily determine which one is which. Can you show the actual code instead of just describing it?David
just added the code as requestedSteviebob
Why do you have a FindDummyObjects method? You don't seem to be respecting the RESTful conventions. What you need is an IEnumerable<Models.DummyObject> Get() method on your DummiesController. When you are doing RESTful routing ALWAYS think in terms of resources.Darin Dimitrov
@Darin Dimitrov I'm just experimenting at the moment. I know that's how I could get it to work, but I'm more interested in why the implementation I've described doesn't work.Steviebob
It doesn't work because out-of-the-box, ASP.NET Web API relies on standard RESTful routing. It expects that if some developer has chosen this framework he probably would like to use REST as convention. If he wants to violate those conventions then he will need to go the hard way and modify his routes, etc... Or maybe just use some RPC framework such as WCF in which there are not resources and the HTTP verb is not dominant.Darin Dimitrov

1 Answers

1
votes

Web API routing has quite a few holes (I'm being polite), you happened to hit on one. This is one of the reasons that they introduced Attribute Routing in Web API2. You might want to try that as it is quite a bit more flexible.