【问题标题】:asp.net mvc web api same controller different function parametersasp.net mvc web api同控制器不同功能参数
【发布时间】:2012-09-24 07:36:29
【问题描述】:

在我的控制器UserApiController中,我有以下功能:

public object GetUsers(string CountryID, string StateID)
{
   //biz
}

public object GetPositions(int CompanyID, int DepartmentID)
{
   //biz
}

在我的控制器SalesApiController中,我有以下功能:

public object GetOrders(string CountryID, int CompanyID)
{
   //biz
}

public object GetProducts(string CountrID, string StateID, int CompanyID)
{
   //biz
}

在 web api 配置中,我可以这样映射:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{CountryID}/{StateID}",
    defaults: new {  }

它适用于 UserApiController.GetUsers,因为函数签名仅与 GetUsers 匹配。

现在,问题:

1.如何定义路由以处理具有相同参数数量的不同功能(在相同或不同控制器内)

2.如何定义路由以处理具有不同参数数量的不同功能(如果可能,在相同或不同控制器中)

【问题讨论】:

  • 既然是webapi,何必担心路由参数呢?为什么不直接使用普通的旧查询字符串参数?
  • 是也不是,我们可以使用老派的查询字符串,但是,最好坚持休息,因为这是 web api 的本质:)

标签: asp.net-mvc routes asp.net-web-api


【解决方案1】:

1.如何定义路由以处理具有相同参数数量的不同功能(在相同或不同控制器内)

这里有几种解决方案。

  • 使用多条路线。以您的 UserApiController 为例,很难有一个路由与 2 个动作一起使用,其中它们具有不同的参数名称。我建议添加以下 2 条路线:

        config.Routes.MapHttpRoute(
            name: "DefaultApi-UserApiGetUsers",
            routeTemplate: "api/{controller}/GetUsers/{CountryID}/{StateID}",
            defaults: new { action = "GetUsers" });
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi-UserApiGetPositions",
            routeTemplate: "api/{controller}/GetPositions/{CompanyID}/{DepartmentID}",
            defaults: new { action = "GetPositions" });
    
  • 按照 danludwig 的建议使用查询字符串参数。这样,你只需要这条路线:

        config.Routes.MapHttpRoute(
            name: "DefaultApiOnlyRoute",
            routeTemplate: "api/{controller}/{action}");
    
    1. api/UserApi/GetUsers?CountryID=USA&StateID=WA
    2. api/UserApi/GetPositions?CompanyID=123&DepartmentID=456

2.如何定义路由以处理具有不同参数数量的不同功能(如果可能,在相同或不同控制器中)

  • 再次,定义多条路线:

        config.Routes.MapHttpRoute(
            name: "DefaultApi-SalesApi2Params",
            routeTemplate: "api/{controller}/{action}/{CountryID}/{CompanyID}");
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi-SalesApi3Params",
            routeTemplate: "api/{controller}/{action}/{CountryID}/{StateID}/{CompanyID}");
    
  • 改为使用查询字符串参数,并且只有一个路由——即上面的“DefaultApiOnlyRoute”。

    1. api/SalesApi/GetOrders?CountryID=USA&CompanyID=123
    2. api/SalesApi/GetProducts?CountryID=USA&StateID=WA&CompanyID=123

希望这会有所帮助。

【讨论】:

  • 嗨,关于查询字符串,我们知道它应该可以工作。说到 web api 路由,我知道我们可以为每个动作分别定义路由,但是想象一下有很多功能,我不相信我们有时间。
  • 您可以查看一些 3rd 方 nuget 包,例如 AttributeRouting。
【解决方案2】:

你可以创建一个像这样的属性,然后用这个属性装饰你的动作。 您仍然需要创建一个与您所做的匹配参数数量的路由一样的路由。

public class SomeAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    for(int i = 0; i <= filterContext.ActionParameters.Count; i++)
    {
      // i + 2 is to not consider controller and action parameters
      filterContext.ActionParameters[filterContext.ActionParameters.ElementAt(i).Key] = 
        Convert.ChangeType(
          filterContext.Controller.ControllerContext.RouteData.Values.ElementAt(i + 2).Value, 
          filterContext.ActionDescriptor.GetParameters()[i].ParameterType
        );
      }
   }
}

希望对你有帮助。

【讨论】:

  • 我可以从代码中推断出您正在动态设置参数值。但是即使参数的名称不同,它也会起作用吗,就像 UserApiController 中的两个函数只映射了一个路由?
  • 是的,它会的。在发布之前,我创建了完全相同的控制器来测试它。它也适用于 SalesApiController.GetOrders 操作。
  • 对不起,我仍然面临 404 错误,能否请您也发布您的 web api 路由映射?
  • 这是路由映射:routes.MapHttpRoute(name: "TwoParametersGenericRoute", routeTemplate: "api/{controller}/{action}/{CountryID}/{StateID}");
  • 所有这些网址都有效:api/UserApi/GetPositions/55/1、api/UserApi/GetUsers/55/1、api/Sales/GetOrders/55/1
猜你喜欢
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多