4

I am trying to add a Get() function in a MVC 6 (Asp .Net 5) Web Api to pass a configuration option as a query string. Here are the two functions that I already have:

[HttpGet]
public IEnumerable<Project> GetAll()
{
    //This is called by http://localhost:53700/api/Project
}

[HttpGet("{id}")]
public Project Get(int id)
{
    //This is called by http://localhost:53700/api/Project/4
}

[HttpGet()]
public dynamic Get([FromQuery] string withUser)
{
    //This doesn't work with http://localhost:53700/api/Project?withUser=true
    //Call routes to first function 'public IEnumerable<Project> GetAll()
}

I've tried several different ways to configure the routing, but MVC 6 is light on documentation. What I really need is a way to pass some configuration options to the list of Projects for sorting, custom filtering etc.

rocky
  • 7,506
  • 3
  • 33
  • 48
bootRom
  • 55
  • 1
  • 1
  • 4
  • 2
    did you try [FromUri] attribute instead of [FromQuery]? in your last method. – Prashant Sep 23 '15 at 13:53
  • 1
    [FromUri] is not an option. The only options are From+ [Body,Form,Header,Query,Route,Services]. – bootRom Sep 23 '15 at 15:21
  • bootRom and @Prashant are correct - This changed from MVC5 to MVC6. That was my problem. – CrazyPyro Jul 19 '16 at 23:36
  • My first question is why are you passing a bool as a string? Second is, you have two of the same items methods, and its totally fine for you to change "GetAll" to just be a "Get." – TGarrett Apr 04 '17 at 17:03

2 Answers2

4

You can't have two [HttpGet]s with the same template in a single controller. I'm using asp.net5-beta7 and in my case it even throws the following exception:

Microsoft.AspNet.Mvc.AmbiguousActionException Multiple actions matched. The following actions matched route data and had all constraints satisfied:

The reason for this is that [From*] attributes are meant for binding, not routing.

The following code should work for you:

    [HttpGet]
    public dynamic Get([FromQuery] string withUser)
    {
        if (string.IsNullOrEmpty(withUser))
        {
            return new string[] { "project1", "project2" };
        }
        else
        {
            return "hello " + withUser;
        }
    }

Also consider using Microsoft.AspNet.Routing.IRouteBuilder.MapRoute() instead of attribute routing. It may give you more freedom defining the routes.

rocky
  • 7,506
  • 3
  • 33
  • 48
  • Yes, that works. I also came across the answer by trial and error, but I didn't understand why it worked. I agree using `IRouteBuilder.MapRoute()` is a cleaner solution. – bootRom Sep 28 '15 at 01:52
0

Accessing the query string is very doable by using either the RESTful routing conventions (enforced by ASP.NET 5 / MVC 6 by default) or by defining custom routes, as explained in this answer.

Here's quick example using custom, attribute-based routes:

[HttpGet("GetLatestItems/{num}")]
public IEnumerable<string> GetLatestItems(int num)
{
    return new string[] { "test", "test2" };
}

For more info about custom routing, read the following article on my blog.

Darkseal
  • 9,205
  • 8
  • 78
  • 111