简体   繁体   中英

ASP.NET Web API Attribute Routing To Wrong Action

I have applied attribute routing on my controller and it'srouting to wrong action. I don't know where I am getting it wrong.

Here is my controller:

using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Description;
using System.Linq;
using System;

namespace Iboo.API.Controllers
{
    public class ClientsController : ApiController
    {
        private readonly IClientRepository _repository;

        public ClientsController(IClientRepository repository)
        {
            _repository = repository;
        }

        // GET: api/Clients
        [Route("api/v1/clients")]
        public IEnumerable<Client> Get()
        {

           //code
        }


        // GET: api/Clients/5
        [HttpGet]
        [ResponseType(typeof(Client))]
        [Route("api/v1/clients/get/{id}")]
        public IHttpActionResult GetClientById(int id)
        {
            //code
        }

        // GET: api/Clients/5
        [HttpGet]
        [ResponseType(typeof(string))]
        [Route("api/v1/clients/{id}/emailid")]
        public IHttpActionResult GetClientEmailId(int id)
        {
            //code
        }        
    }
}

I am specifically interested in the GetClientEmailId method. Below is my WebApiConfig

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    var container = new UnityContainer();
    container.RegisterType<IClientRepository, ClientRepository>(new 
    HierarchicalLifetimeManager());


    // Web API routes
    config.MapHttpAttributeRoutes();

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

My Global.asax.cs is as follows

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

In the browser If I type http://localhost:54919/api/v1/clients/?id=1/getemailid it's taking me to http://localhost:54919/api/v1/clients which is not what I want.

If I try http://localhost:54919/api/v1/clients/1/getemailid I am getting a 404 error.

I am not sure as to what I'm getting wrong.

You can try using the route prefix on the controller.

[RoutePrefix("api/v1/clients")]
public class ClientsController : ApiController
{
    // GET: api/Clients/5
    [ResponseType(typeof(string))]
    [Route("{id:int}/emailid"),HttpGet]
    public IHttpActionResult GetClientEmailId(int id)
    {
        //code
    }     
}

You said:

In the browser If I type http://localhost:54919/api/v1/clients/?id=1/getemailid it's taking me to http://localhost:54919/api/v1/clients which is not what I want.

From the way your routes are set up, it looks like you need to go to http://localhost:54919/api/v1/client/1/emailid to get to the route you want

To explain the difference, when you call http://localhost:54919/api/v1/clients/?id=1/getemailid the route that would match that is something like:

[Route("api/v1/clients")]
public IHttpActionResult GetClientEmailId(string id)
{
    //code
}

because you've added the id parameter as a querystring parameter. In this case, the id argument would have a value of 1/getemailid which doesn't make much sense.

by using the route parameters (by replacing ?id=1/getemailid with 1/emailid ) you will actually match the route you want to

You are calling the wrong URLs according to routes on the actions. you get 404 because the URL you call does not match to any of the route templates you have on your actions

[RoutePrefix("api/v1/clients")]
public class ClientsController : ApiController {
    //...other code removed for brevity

    [HttpGet]
    [Route("")] //Matches GET api/v1/Clients
    public IHttpActionResult Get() {
       //code
    }

    [HttpGet]
    [ResponseType(typeof(Client))]
    [Route("{id:int}")] //Matches GET api/v1/Clients/5
    public IHttpActionResult GetClientById(int id) {
        //code
    }

    [HttpGet]
    [ResponseType(typeof(string))]
    [Route("{id:int}/emailid")] //Matches GET api/v1/Clients/5/emailid
    public IHttpActionResult GetClientEmailId(int id) {
        //code
    }        
}

Take note of the expected URLs in the comments

You should also read up on Attribute Routing in ASP.NET Web API 2 to get a better understanding of how to do attribute-routing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM