在 ASP.NET Web API 中使用多个 Get 方法进行路由
Posted
技术标签:
【中文标题】在 ASP.NET Web API 中使用多个 Get 方法进行路由【英文标题】:Routing with multiple Get methods in ASP.NET Web API 【发布时间】:2012-09-28 08:11:57 【问题描述】:我正在使用带有 ASP.NET MVC 的 Web Api,我对它很陌生。我已经在 asp.net 网站上浏览了一些演示,我正在尝试执行以下操作。
我有 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
对于上述所有方法,我希望我的 web api 如下所示
列表获取() =api/customers/
客户 GetCustomerById(字符串 ID) = api/customers/13
列出GetCustomerByCurrentMonth() = /customers/currentMonth
客户GetCustomerByUsername(字符串用户名)=/customers/customerByUsername/yasser
我尝试对路由进行更改,但由于我是新手,不太了解。
所以,请有人帮助我理解并指导我应该如何做到这一点。谢谢
【问题讨论】:
查看路由和操作过滤器 Api controller declaring more than one Get statement 的可能重复项 【参考方案1】:从这里Routing in Asp.net Mvc 4 and Web Api
Darin Dimitrov 发布了一个非常适合我的答案。
上面写着……
你可以有几条路线:
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"
);
【讨论】:
请看我的question 非常有帮助。我创建了多个 Get 方法,但没有将它们注册到 WebApiConfig 文件中。注册后就可以访问了。【参考方案2】:首先,添加带有 action 的新路由:
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
);
然后使用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
【讨论】:
啊!这看起来很有希望,现在将尝试一下。 我试过了,除了api/customers/
和/customers/customerByUsername/yasser
之外的所有工作我应该做些什么改变
我在问题上犯了一个错误,我已经更正了。请帮助
我仍然收到 http://localhost:61821/api/customers/
的 500 内部服务器错误,非常感谢您在这方面帮助我,请再次帮助我 :)
这在纸上看起来不错,但实际上不起作用。您必须在这篇文章中执行类似于第二个答案的操作:***.com/questions/9569270/… 诀窍是在第一个路由中的 id 参数上添加一个 int 约束,并将默认操作设置为“Get”以及第二个路由上的 HttpGet 约束【参考方案3】:
您还将为设置路线指定行动路线
[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
【讨论】:
我认为这个答案简单明了,甚至与 .NET Core 兼容。然而,可以避免重复的路由前缀。见:***.com/questions/12775590/…【参考方案4】:这个问题已经有很多很好的答案了。然而,现在 Route 配置有点“弃用”。较新版本的 MVC (.NET Core) 不支持它。所以最好习惯它:)
所以我同意所有使用属性样式路由的答案。但我一直注意到每个人都重复了路线的基础部分(api/...)。最好在 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
【讨论】:
【参考方案5】:只有一条路线就够了
config.Routes.MapHttpRoute("DefaultApiWithAction", "controller/action");
并且需要在所有动作中指定属性HttpGet或HttpPost。
[HttpGet]
public IEnumerable<object> TestGet1()
return new string[] "value1", "value2" ;
[HttpGet]
public IEnumerable<object> TestGet2()
return new string[] "value3", "value4" ;
【讨论】:
【参考方案6】:您可能不需要对路由进行任何更改。只需在您的 customersController.cs 文件中添加以下四个方法:
public ActionResult Index()
public ActionResult currentMonth()
public ActionResult customerById(int id)
public ActionResult customerByUsername(string userName)
将相关代码放入方法中。使用提供的默认路由,您应该根据给定 url 的操作和参数从控制器获得适当的操作结果。
修改你的默认路由为:
routes.MapRoute(
"Default", // Route name
"controller/action/id", // URL with parameters
new controller = "Api", action = "Index", id = UrlParameter.Optional // Parameter defaults
);
【讨论】:
正确。控制器负责呈现给定的动作结果。要使这些方法像这样工作,您必须将其重命名为 customerController 或更改路由。如果要将控制器名称保留为 apicontroller,请更改路由并将控制器的默认值设置为“Api”而不是“Home”。 是的,我想保持名称不变,你能告诉我如何为此编写路由吗? 我已经编辑了路由,看看我如何将默认控制器从“Home”替换为“Api” 我不希望将索引作为控制器中的操作 索引用于您的默认网址“api/customers/”。您不必在 url 中放入 index,当未指定任何操作时,它会自动执行 Index 操作。在路线中看到,我们将“索引”作为默认操作。【参考方案7】: // 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");
【讨论】:
【参考方案8】:我有两个 get 方法,参数相同或没有参数
[Route("api/ControllerName/FirstList")]
[HttpGet]
public IHttpActionResult FirstList()
[Route("api/ControllerName/SecondList")]
[HttpGet]
public IHttpActionResult SecondList()
只需在AppStart=>WebApiConfig.cs
中定义自定义路由=>在注册方法下
config.Routes.MapHttpRoute(
name: "GetFirstList",
routeTemplate: "api/Controllername/FirstList"
);
config.Routes.MapHttpRoute(
name: "GetSecondList",
routeTemplate: "api/Controllername/SecondList"
);
【讨论】:
【参考方案9】:在阅读了很多答案后,我终于想通了。
首先,我在 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"
);
然后,从控制器函数中删除 ActionName、Route 等。所以基本上这是我的控制器;
// 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);
现在我可以使用以下 url 示例(带有名称和 id)运行;
http://localhost:49787/api/Countries/GetCountriesByName/France
http://localhost:49787/api/Countries/1
【讨论】:
【参考方案10】: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" ;
【讨论】:
以上是关于在 ASP.NET Web API 中使用多个 Get 方法进行路由的主要内容,如果未能解决你的问题,请参考以下文章
从 ASP.NET MVC Web API 中的多个表单数据键接收文件
(Asp.Net MVC / Web-Api)中具有相同身份验证系统的多个项目
我应该如何将多个参数传递给 ASP.Net Web API GET?