26

In ASP.NET MVC WebAPI project by default we have created following controller

 public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

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

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

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

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

But is possible to add here any custom methods so they can support get/post as well?

Thank you!

NoWar
  • 36,338
  • 80
  • 323
  • 498

4 Answers4

22

You can use attributes such as the RoutePrefix with the Http type.

[Route("ChangePassword")]
[HttpPost] // There are HttpGet, HttpPost, HttpPut, HttpDelete.
public async Task<IHttpActionResult> ChangePassword(ChangePasswordModel model)
{        
}

The http type will map it back to its correct method in combination with the Route name.

Shawn Mclean
  • 56,733
  • 95
  • 279
  • 406
  • Hi! When I try to input `[Route("MyPath")]` VS2013 does not resolve it. Also I cannot debug it. It gives me an error about `[Route("MyPath")]`. Do you know what is the issue? – NoWar Jul 19 '14 at 18:20
  • 1
    @ClarkKent Its native in MVC 5 and WebApi 2, otherwise, you may have to check nuget for `AttributeRouting` – Shawn Mclean Jul 20 '14 at 02:33
15

I am not sure I follow as you have GET and POST right there in your code, but in any case you have other options:

Option 1

First, you can configure your custom Routes in the App_Start folder in the WebApiConfig.cs file. Here is what I normally use:

    // GET /api/{resource}/{action}
    config.Routes.MapHttpRoute(
        name: "Web API RPC",
        routeTemplate: "{controller}/{action}",
        defaults: new { },
        constraints: new { action = @"[A-Za-z]+", httpMethod = new HttpMethodConstraint("GET") }
        );
    
    // GET|PUT|DELETE /api/{resource}/{id}/{code}
    config.Routes.MapHttpRoute(
        name: "Web API Resource",
        routeTemplate: "{controller}/{id}/{code}",
        defaults: new { code = RouteParameter.Optional },
        constraints: new { id = @"\d+" }
        );

    // GET /api/{resource}
    config.Routes.MapHttpRoute(
        name: "Web API Get All",
        routeTemplate: "{controller}",
        defaults: new { action = "Get" },
        constraints: new { httpMethod = new HttpMethodConstraint("GET") }
        );

    // PUT /api/{resource}
    config.Routes.MapHttpRoute(
        name: "Web API Update",
        routeTemplate: "{controller}",
        defaults: new { action = "Put" },
        constraints: new { httpMethod = new HttpMethodConstraint("PUT") }
        );

    // POST /api/{resource}
    config.Routes.MapHttpRoute(
        name: "Web API Post",
        routeTemplate: "{controller}",
        defaults: new { action = "Post" },
        constraints: new { httpMethod = new HttpMethodConstraint("POST") }
        );

    // POST /api/{resource}/{action}
    config.Routes.MapHttpRoute(
        name: "Web API RPC Post",
        routeTemplate: "{controller}/{action}",
        defaults: new { },
        constraints: new { action = @"[A-Za-z]+", httpMethod = new HttpMethodConstraint("POST") }
        );

I use a combination of RESTful endpoints as well as RPC endpoints. For some purists, this is grounds for a holy war. For me, I use a combination of the two because it is a powerful combination and I can't find any sane reason not to.

Option 2

As the others have pointed out and as I myself am doing more of these days, use attribute routing:

    [HttpGet]
    [GET("SomeController/SomeUrlSegment/{someParameter}")]
    public int SomeUrlSegment(string someParameter)
    {
        //do stuff
    }

I needed a NuGet package for attribute routing to make this work (just search NuGet for "Attribute Routing"), but I think that MVC 5/WebAPI 2 has it natively.

Hope this helps.

Community
  • 1
  • 1
Matt Cashatt
  • 23,490
  • 28
  • 78
  • 111
13

You could use attribute routing:

[Route("customers/{customerId}/orders")]
public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }

Some documentation to get you started:

http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

Iain
  • 6,392
  • 2
  • 30
  • 50
  • 1
    Hi! When I try to input `[Route("MyPath")]` VS2013 does not resolve it. Also I cannot debug it. It gives me an error about `[Route("MyPath")]`. Do you know what is the issue? – NoWar Jul 19 '14 at 18:24
  • 1
    @ClarkKent--Search NuGet for "attribute routing". You probably need a DLL or two. – Matt Cashatt Jul 19 '14 at 18:37
1

First Put this route to webapiconfig.cs

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

Now you can add actions to your controllers like this

 [HttpPost]
    public void Upload()
    {
           //Do some thing
    }

I decorated upload action with httppost attribute that means this action accept just only post requests , if you want to actions to be GET , you can remove attribute or just decorate to your suite

elia07
  • 322
  • 2
  • 7