NoWar
NoWar

Reputation: 37642

How to add custom methods to ASP.NET WebAPI controller?

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!

Upvotes: 27

Views: 43739

Answers (4)

elia07
elia07

Reputation: 322

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

Upvotes: 1

Matt Cashatt
Matt Cashatt

Reputation: 24218

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.

Upvotes: 15

Shawn Mclean
Shawn Mclean

Reputation: 57479

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.

Upvotes: 22

Iain
Iain

Reputation: 6472

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

Upvotes: 13

Related Questions