【问题标题】:ASP.NET Web Api ignores RouteParameter.Optional when selecting the action选择操作时 ASP.NET Web Api 忽略 RouteParameter.Optional
【发布时间】:2012-11-26 05:39:16
【问题描述】:

我通过以下步骤发现了这个问题:

  1. 使用已安装的项目模板创建一个新的 WebApi 项目

  2. 进入Controllers/ValuesController.cs,有两个Get方法如下:

    public IEnumerable<string> Get() //这个提供GetAll函数

    public string Get(int id) // 这个是 GetOneById

  3. 我不喜欢这样的设计,因为我觉得这两个api方法可以合二为一:

    public IEnumerable<string> Get(string ids)当ids为null时,返回所有记录,否则按ids返回结果(类似id1,id2,id3...)

我也修改了路线:

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

现在我想一切都准备好了。但是,当我在浏览器中访问/values(未指定 ids 参数)时,我被告知“未找到任何操作”,直到我为 ids 添加默认值:

public IEnumerable<string> Get(string ids = null)

从现在开始,一切都按我的预期进行。我仍然无法在路由中移动defaults 参数。这意味着:代码两次将 ids 参数声明为可选

查看位于System.Web.Http.Controllers.ActionSelectorCacheItem.FindActionUsingRouteAndQueryParameters 方法的MVC4 的源代码,我可以看到在找到正确的操作 时忽略了路由中定义的可选参数。我个人认为这真的很糟糕,即使解决方法也很容易。还是我误解了路线和动作方法之间的关系?我认为路由是用于帮助请求找到其相应操作的规则,而“参数是可选的”正是规则的一部分。

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    您可能有一个论点,对于相对直接的事情,这感觉像是一个尴尬的解决方案,但我认为根本原因是因为您试图将 'GetAll' 和 'GetOneById' 滚动到同一个方法中。

    如果您愿意在控制器中拆分方法,则可以将路由配置排除在外。恕我直言,这不是一件坏事;它符合关注点分离原则。这也不意味着任何重复代码,因为您可以集中逻辑来访问您想要返回的对象。

    这些控制器方法应该可以为您提供所需的路由,而无需调整路由配置:

    [HttpGet]
    public IEnumerable<string> GetAll()
    {
        return GetStrings(new int[]{});
    }
    
    [HttpGet]
    public string GetOneById(int id)
    {
        return GetStrings(new int[]{id}).FirstOrDefault();
    }
    
    private IEnumerable<string> GetStrings(int[] ids)
    {
         return // fetch strings using int array
    }
    

    【讨论】:

      【解决方案2】:

      您可以选择将值作为查询字符串

      public class PaymentsController : ApiController {
              [HttpGet]
              public Person GetValues(string ids = null)
              {
                  return new Person() { FirstName = "Michael" };
              }
          }
      
          public class Person
          {
              public string FirstName { get; set; }
          }
      }
      

      我可以同时访问这条路线:

      1. /api/payments/getvalues/?ids=123
      2. /api/payments/getvalues/

      注意:除了默认路由之外没有任何特殊路由

      【讨论】:

        猜你喜欢
        • 2013-06-15
        • 2017-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多