【问题标题】:how to configure this route for webapi?如何为 webapi 配置此路由?
【发布时间】:2013-09-25 01:57:40
【问题描述】:

我有一个控制器来获取一个资源(比如员工),它有两个属性(比如 CategoryId 和 DepartmentId)。我需要配置路由以支持以下 URL:

~/api/employees/1234 [to get the employee with employeeId=1234]
~/api/employees [to get all the employees]
~/api/employees?departmentid=1 [to get all the employees with departmentId=1]

控制器代码如下所示:

public IEnumerable<Employee> Get()
{
    ....
}

public IEnumerable<Employee> Get(int employeeId, int departmentId = -1, int categoryId = -1)
{
    .....
}

如何为这个控制器配置路由?

谢谢

【问题讨论】:

    标签: c# asp.net-web-api routes


    【解决方案1】:

    对于任何 querystyring 参数,在路由端没有什么可做的:只需让控制器方法参数与 qs 参数名称匹配(不区分大小写)。

    如果您的方法参数引用的是 uri 段,则方法参数名称必须与大括号之间的路由参数/段匹配

    routes.MapHttpRoute(
        name: "API Default",
        routeTemplate: "/api/{controller}/{employeeId}",
        defaults: new { id = RouteParameter.Optional }
    );
    

    这意味着您需要一个具有以下方法的控制器

    public class EmployeesController : ApiController
    {
    public IEnumerable<Employee> Get(int employeeId){...} 
    }
    

    请记住,除非您使用操作,否则您的控制器上的每个 http 动词只能使用一种方法。
    换句话说,除非您对它们都使用显式操作,否则您的示例对于动词 get 有 2 种方法将不起作用。

    【讨论】:

    • 我知道查询字符串参数与路由无关。假设您希望在EmployeesController 中使用相同的参数进行另一个“获取”操作,如下所示:public IEnumerable Get(int DepartmentId = 1){....}。您将如何配置此操作方法的路由?
    • 如果您想从同一个 url 段读取不同的参数(根据您的示例具有不同的名称),您需要创建 2 个不同的控制器。如果您需要在同一个控制器中获得 2 个 get,则为每个 get 分配一个特定的操作,但它们不能从相同的 url 段读取相同的不同参数名称:您可能需要至少其中一个的查询字符串,特别是“DepartmentId”使更多有意义,因为控制器已被命名为“员工”
    【解决方案2】:

    您是否考虑过使用属性路由?我们现在广泛使用属性路由,以至于我们完全摆脱了使用 MapHttpRoute 的默认 /controller/action 类型路由。

    相反,我们按如下方式装饰我们的控制器。首先,我们为控制器创建一个路由前缀,以便我们知道我们需要的基本路由是什么

    /// <summary>   A controller for handling products. </summary>
    [RoutePrefix("api/purchasing/locations/{locationid}/products")]
    public class ProductsController : PurchasingController
    {
    

    然后对于控制器中的每个动作,我们将其装饰如下:

        [Route("", Name = "GetAllProducts")]
        public IHttpActionResult GetAllProducts(int locationid, ODataQueryOptions<FourthPurchasingAPI.Models.Product> queryOptions)
        {
            IList<Product> products = this.GetProducts(locationid);
    

        [Route("{productid}", Name = "GetProductById")]
        public IHttpActionResult GetProduct(int locationid, string productid)
        {
            Product product = this.GetProductByID(locationid, productid);
    

    所以对api/purchasing/locations/1/products/ 的调用将解析到名为“GetAllProducts”的路由 并且对api/purchasing/locations/1/products/1 的调用将解析为名为“GetProductById”的路由

    然后您可以在控制器中创建另一个具有相同签名的 GetProduct 操作,只需适当地设置属性路由,例如

        [Route("/department/{departmentId}", Name = "GetAllProductsForDepartment")]
        public IHttpActionResult GetAllProductsWithDeptId(int locationid, int departmentId)
        {
            IList<Product> products = this.GetProducts(locationid, departmentId);
    

    现在对api/purchasing/locations/1/products/department/1234 的调用将解析为名为“GetAllProductsForDepartment”的路由

    我知道这个示例使用的是 Web Api 2,但请查看 this link 以了解 Web Api 中的属性路由。它应该完全相同,而不是您将返回 IHttpActionResult 以外的其他内容。

    【讨论】:

      猜你喜欢
      • 2017-08-05
      • 1970-01-01
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多