简体   繁体   English

在ASP.NET Web API中使用多个Get方法进行路由

[英]Routing with multiple Get methods in ASP.NET Web API

I am using Web Api with ASP.NET MVC, and I am very new to it. 我正在使用Web Api和ASP.NET MVC,我对它很新。 I have gone through some demo on asp.net website and I am trying to do the following. 我已经在asp.net网站上进行了一些演示,我正在尝试执行以下操作。

I have 4 get methods, with the following signatures 我有4个get方法,具有以下签名

public List<Customer> Get()
{
    // gets all customer
}

public List<Customer> GetCustomerByCurrentMonth()
{
    // gets some customer on some logic
}

public Customer GetCustomerById(string id)
{
    // gets a single customer using id
}

public Customer GetCustomerByUsername(string username)
{
    // gets a single customer using username
}

For all the methods above I would like to have my web api somewhat like as shown below 对于上面的所有方法,我希望我的web api有点像下面所示

  • List Get() = api/customers/ 列表Get()= api/customers/
  • Customer GetCustomerById(string Id) = api/customers/13 Customer GetCustomerById(string Id)= api/customers/13
  • List GetCustomerByCurrentMonth() = /customers/currentMonth 列出GetCustomerByCurrentMonth()= /customers/currentMonth
  • Customer GetCustomerByUsername(string username) = /customers/customerByUsername/yasser Customer GetCustomerByUsername(string username)= /customers/customerByUsername/yasser

I tried making changes to routing, but as I am new to it, could'nt understand much. 我尝试对路由进行更改,但由于我是新手,因此无法理解。

So, please can some one help me understand and guide me on how this should be done. 所以,请一些人帮助我理解并指导我如何做到这一点。 Thanks 谢谢

From here Routing in Asp.net Mvc 4 and Web Api 从这里路由Asp.net Mvc 4和Web Api

Darin Dimitrov has posted a very good answer which is working for me. Darin Dimitrov发布了一个非常好的答案,对我有用。

It says... 它说...

You could have a couple of routes: 你可以有几条路线:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "ApiById",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"^[0-9]+$" }
        );

        config.Routes.MapHttpRoute(
            name: "ApiByName",
            routeTemplate: "api/{controller}/{action}/{name}",
            defaults: null,
            constraints: new { name = @"^[a-z]+$" }
        );

        config.Routes.MapHttpRoute(
            name: "ApiByAction",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { action = "Get" }
        );
    }
}

First, add new route with action on top: 首先,添加带有操作的新路线:

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

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

Then use ActionName attribute to map: 然后使用ActionName属性进行映射:

[HttpGet]
public List<Customer> Get()
{
    //gets all customer
}

[ActionName("CurrentMonth")]
public List<Customer> GetCustomerByCurrentMonth()
{
    //gets some customer on some logic
}

[ActionName("customerById")]
public Customer GetCustomerById(string id)
{
    //gets a single customer using id
}

[ActionName("customerByUsername")]
public Customer GetCustomerByUsername(string username)
{
    //gets a single customer using username
}

Also you will specify route on action for set route 您还将为设置路线指定行动路线

[HttpGet]
[Route("api/customers/")]
public List<Customer> Get()
{
   //gets all customer logic
}

[HttpGet]
[Route("api/customers/currentMonth")]
public List<Customer> GetCustomerByCurrentMonth()
{
     //gets some customer 
}

[HttpGet]
[Route("api/customers/{id}")]
public Customer GetCustomerById(string id)
{
  //gets a single customer by specified id
}
[HttpGet]
[Route("api/customers/customerByUsername/{username}")]
public Customer GetCustomerByUsername(string username)
{
    //gets customer by its username
}

Only one route enough for this 只有一条路线足够了

config.Routes.MapHttpRoute("DefaultApiWithAction", "{controller}/{action}");

And need to specify attribute HttpGet or HttpPost in all actions. 并且需要在所有操作中指定属性HttpGetHttpPost

[HttpGet]
public IEnumerable<object> TestGet1()
{
    return new string[] { "value1", "value2" };
}

[HttpGet]
public IEnumerable<object> TestGet2()
{
    return new string[] { "value3", "value4" };
}

There are lots of good answers already for this question. 这个问题已经有很多好的答案了。 However nowadays Route configuration is sort of "deprecated". 但是现在Route配置有点“已弃用”。 The newer version of MVC (.NET Core) does not support it. 较新版本的MVC(.NET Core)不支持它。 So better to get use to it :) 所以更好地利用它:)

So I agree with all the answers which uses Attribute style routing. 所以我同意所有使用属性样式路由的答案。 But I keep noticing that everyone repeated the base part of the route (api/...). 但我一直注意到每个人都重复了路线的基础部分(api / ...)。 It is better to apply a [RoutePrefix] attribute on top of the Controller class and don't repeat the same string over and over again. 最好在Controller类的顶部应用[RoutePrefix]属性,并且不要反复重复相同的字符串。

[RoutePrefix("api/customers")]
public class MyController : Controller
{
 [HttpGet]
 public List<Customer> Get()
 {
   //gets all customer logic
 }

 [HttpGet]
 [Route("currentMonth")]
 public List<Customer> GetCustomerByCurrentMonth()
 {
     //gets some customer 
 }

 [HttpGet]
 [Route("{id}")]
 public Customer GetCustomerById(string id)
 {
  //gets a single customer by specified id
 }
 [HttpGet]
 [Route("customerByUsername/{username}")]
 public Customer GetCustomerByUsername(string username)
 {
    //gets customer by its username
 }
}

After reading lots of answers finally I figured out. 在读完很多答案之后我终于明白了。

First, I added 3 different routes into WebApiConfig.cs 首先,我在WebApiConfig.cs中添加了3条不同的路由

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

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "ApiById",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional },
        constraints: new { id = @"^[0-9]+$" }
    );

    config.Routes.MapHttpRoute(
        name: "ApiByName",
        routeTemplate: "api/{controller}/{action}/{name}",
        defaults: null,
        constraints: new { name = @"^[a-z]+$" }
    );

    config.Routes.MapHttpRoute(
        name: "ApiByAction",
        routeTemplate: "api/{controller}/{action}",
        defaults: new { action = "Get" }
    );
}

Then, removed ActionName, Route, etc.. from the controller functions. 然后,从控制器函数中删除ActionName,Route等。 So basically this is my controller; 所以基本上这是我的控制器;

// GET: api/Countries/5
[ResponseType(typeof(Countries))]
//[ActionName("CountryById")]
public async Task<IHttpActionResult> GetCountries(int id)
{
    Countries countries = await db.Countries.FindAsync(id);
    if (countries == null)
    {
        return NotFound();
    }

    return Ok(countries);
}

// GET: api/Countries/tur
//[ResponseType(typeof(Countries))]
////[Route("api/CountriesByName/{anyString}")]
////[ActionName("CountriesByName")]
//[HttpGet]
[ResponseType(typeof(Countries))]
//[ActionName("CountryByName")]
public async Task<IHttpActionResult> GetCountriesByName(string name)
{
    var countries = await db.Countries
            .Where(s=>s.Country.ToString().StartsWith(name))
            .ToListAsync();

    if (countries == null)
    {
        return NotFound();
    }

    return Ok(countries);
}

Now I am able to run with following url samples(with name and with id); 现在我可以运行以下url示例(带名称和id);

http://localhost:49787/api/Countries/GetCountriesByName/France HTTP://本地主机:49787 / API /国家/ GetCountriesByName /法国

http://localhost:49787/api/Countries/1 HTTP://本地主机:49787 / API /国家/ 1

You might not need to make any change in the routing. 您可能不需要对路由进行任何更改。 Just add following four methods in your customersController.cs file: 只需在customersController.cs文件中添加以下四种方法:

public ActionResult Index()
{
}

public ActionResult currentMonth()
{
}

public ActionResult customerById(int id)
{
}


public ActionResult customerByUsername(string userName)
{
}

Put the relevant code in the method. 将相关代码放在方法中。 With the default routing supplied, you should get appropriate action result from the controller based on the action and parameters for your given urls. 使用提供的默认路由,您应该根据给定URL的操作和参数从控制器获取适当的操作结果。

Modify your default route as: 将您的默认路由修改为:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Api", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
  // this piece of code in the WebApiConfig.cs file or your custom bootstrap application class
  // define two types of routes 1. DefaultActionApi  and 2. DefaultApi as below

   config.Routes.MapHttpRoute("DefaultActionApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
   config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { action = "Default", id = RouteParameter.Optional });

  // decorate the controller action method with [ActionName("Default")] which need to invoked with below url
  // http://localhost:XXXXX/api/Demo/ -- will invoke the Get method of Demo controller
  // http://localhost:XXXXX/api/Demo/GetAll -- will invoke the GetAll method of Demo controller
  // http://localhost:XXXXX/api/Demo/GetById -- will invoke the GetById method of Demo controller
  // http://localhost:57870/api/Demo/CustomGetDetails -- will invoke the CustomGetDetails method of Demo controller
  // http://localhost:57870/api/Demo/DemoGet -- will invoke the DemoGet method of Demo controller


 public class DemoController : ApiController
 {
    // Mark the method with ActionName  attribute (defined in MapRoutes) 
    [ActionName("Default")]
    public HttpResponseMessage Get()
    {
        return Request.CreateResponse(HttpStatusCode.OK, "Get Method");
    }

    public HttpResponseMessage GetAll()
    {
        return Request.CreateResponse(HttpStatusCode.OK, "GetAll Method");
    }

    public HttpResponseMessage GetById()
    {
        return Request.CreateResponse(HttpStatusCode.OK, "Getby Id Method");
    }

    //Custom Method name
    [HttpGet]
    public HttpResponseMessage DemoGet()
    {
        return Request.CreateResponse(HttpStatusCode.OK, "DemoGet Method");
    }

    //Custom Method name
    [HttpGet]
    public HttpResponseMessage CustomGetDetails()
    {
        return Request.CreateResponse(HttpStatusCode.OK, "CustomGetDetails Method");
    }
}

I have two get methods with same or no parameters 我有两个get方法,相同或没有参数

[Route("api/ControllerName/FirstList")]
[HttpGet]
public IHttpActionResult FirstList()
{
}

[Route("api/ControllerName/SecondList")]
[HttpGet]
public IHttpActionResult SecondList()
{
}

Just define custom routes in AppStart=>WebApiConfig.cs => under register method 只需在注册方法下在AppStart=>WebApiConfig.cs =>中定义自定义路由

config.Routes.MapHttpRoute(
       name: "GetFirstList",
       routeTemplate: "api/Controllername/FirstList"          
       );
config.Routes.MapHttpRoute(
       name: "GetSecondList",
       routeTemplate: "api/Controllername/SecondList"          
       );
using Routing.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace Routing.Controllers
{
    public class StudentsController : ApiController
    {
        static List<Students> Lststudents =
              new List<Students>() { new Students { id=1, name="kim" },
           new Students { id=2, name="aman" },
            new Students { id=3, name="shikha" },
            new Students { id=4, name="ria" } };

        [HttpGet]
        public IEnumerable<Students> getlist()
        {
            return Lststudents;
        }

        [HttpGet]
        public Students getcurrentstudent(int id)
        {
            return Lststudents.FirstOrDefault(e => e.id == id);
        }
        [HttpGet]
        [Route("api/Students/{id}/course")]
        public IEnumerable<string> getcurrentCourse(int id)
        {
            if (id == 1)
                return new List<string>() { "emgili", "hindi", "pun" };
            if (id == 2)
                return new List<string>() { "math" };
            if (id == 3)
                return new List<string>() { "c#", "webapi" };
            else return new List<string>() { };
        }

        [HttpGet]
        [Route("api/students/{id}/{name}")]
        public IEnumerable<Students> getlist(int id, string name)
        { return Lststudents.Where(e => e.id == id && e.name == name).ToList(); }

        [HttpGet]
        public IEnumerable<string> getlistcourse(int id, string name)
        {
            if (id == 1 && name == "kim")
                return new List<string>() { "emgili", "hindi", "pun" };
            if (id == 2 && name == "aman")
                return new List<string>() { "math" };
            else return new List<string>() { "no data" };
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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