2

I am unable to get basic routing to work in my asp.net web api project. I have followed examples on asp.net (http://www.asp.net/web-api/overview/web-api-routing-and-actions) and I have searched throughout stackoverflow in an attempt to find a solution. Whatever examples I have tried, I cannot get attribute routing to work.

This is my controller:

public class EmployeeController : ApiController
{
    private readonly IRepository<Employee> _employees; 

    public EmployeeController(IRepository<Employee> repo)
    {
        _employees = repo;
    }


    [Route("")]
    public IEnumerable<Employee> GetEmployees()
    {
        return _employees.Queryable();
    }


    [Route("{id:int}")]
    public Employee GetEmployee(int id)
    {
        return _employees.Queryable().FirstOrDefault();
    }
}

This is my Global.asax.cs:

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }
}

This is my WebApiConfig.cs:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

No matter what I attempt, I end up either with a 404 or as in the case of the code above, I get the message

No HTTP resource was found that matches the request URI 'http://localhost:2442/api/employee/1'.

No action was found on the controller 'Employee' that matches the request.

with or without the integer parameter.

2 Answers 2

3

Either use the attribute routing for your controller, or don't use it all. That means you need to decorate your controller with RoutePrefix instead of relying on the configured routes.

[RoutePrefix("api/employee")
public class EmployeeController : ApiController
{
    private readonly IRepository<Employee> _employees; 
    public EmployeeController(IRepository<Employee> repo)
    {
        _employees = repo;
    }
    [Route("")]
    public IEnumerable<Employee> GetEmployees()
    {
        return _employees.Queryable();
    }
    [Route("{id}")]
    public Employee GetEmployee(int id)
    {
        return _employees.Queryable().FirstOrDefault();
    }
}

or in the below example, we rely on the defined route instead of using attribute routing.

public class EmployeeController : ApiController
{
    private readonly IRepository<Employee> _employees; 
    public EmployeeController(IRepository<Employee> repo)
    {
        _employees = repo;
    }
    public IEnumerable<Employee> GetEmployees()
    {
        return _employees.Queryable();
    }
    public Employee GetEmployee(int id)
    {
        return _employees.Queryable().FirstOrDefault();
    }
}

If you mix and match, it confuses things.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for clearing this up. I was under the impression that Route attributes on methods take precedence over the default route mapping
@transporter_room_3 I believe the reason it took precedence was because you have config.MapHttpAttributeRoutes(); before you mapped the other route. However, the reason you got the error was that there was no route prefix, therefore the URL you would have needed to request it was was ~/1 because in my experience you can't mix and match attribute routing with normal routing on the same controller. If you don't specify a RoutePrefix, I don't believe it will use the controller mapped in a later route, which is why ~/api/employee/1 gives you an error.
3

Did you try putting the RoutePrefix attribute on your class like this:

[RoutePrefix("api/employee")]
public class EmployeeController : ApiController

1 Comment

That does the trick, wow. But I was under the impression (from reading the tuts on asp.net), that you don't have to use the route prefix attribute? That I would be able to attribute a method with [Route("api/employee/name")] for instance. But that does not seem to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.