【问题标题】:Web-Api Route resolution Array Model BindingWeb-Api 路由解析数组模型绑定
【发布时间】:2017-12-21 04:08:29
【问题描述】:

我正在尝试了解 Web-Api 如何解析路由。我有两条使用相同基本路径的路线

[WriteRoute(DivisionAPIRoutes.PAYROLL_IMPORT_PTO)]
[HttpPost]
public void ImportPTOByIds(GlobalEntityKey<IDivision> parentId, GlobalEntityKey<IDivisionPayCalendar> id,
    ImportPTORequestDTO importPTORequest, [FromUri] GlobalEntityKey<IPTORequest>[] ptoRequestIds)
{
    GlobalFactory<IEmployeePTOListService>.Instance.ImportPTOByIds(parentId, id, ptoRequestIds, importPTORequest);
}

[WriteRoute(DivisionAPIRoutes.PAYROLL_IMPORT_PTO)]
[HttpPost]
public void ImportPTOByFilter(GlobalEntityKey<IDivision> parentId, GlobalEntityKey<IDivisionPayCalendar> id, ImportPTORequestDTO importPTORequest, string filterOptions,
    [FromUri] GlobalEntityKey<IPTORequest>[] excludedPTORequestIds)
{
    var filterOptionsDTO = JsonConvert.DeserializeObject<FilterOptionsDTO>(filterOptions);
    GlobalFactory<IEmployeePTOListService>.Instance.ImportPTOByFilter(parentId, id, filterOptionsDTO, excludedPTORequestIds, importPTORequest);
}

注意:默认情况下,构建 CLR 类型 string、int 是从 URI 中检索的

我正在发出一个工作正常的发布请求,但我试图了解路由如何解析为方法的底层逻辑:

(为了方便解码)

https://localhost/api/paystream/v1/divisions/1af4edea-d442-4fda-b29d-02c42951c0d0/payrolls/cd2ed43d-0f3d-48fb-8d00-15294a8fa06e/_actions/import-pto?filterOptions={"query":"","filterParameters":[{"fieldName":"RequestStartDate","parsebleValue":"2016-01-01","filterType":"GreaterThanOrEqual"},{ "fieldName":"RequestStartDate","parsebleValue":"2017-12-31","filterType":"LessThanOrEqual"}]}

帖子正文:{ AlwaysCreateNewCheck:假, PayBatchType:'支票', PayBatchId:'1903771' }

如果我从请求中省略了排除的 PTORequestIds。这仍将解析为ImportPTOByFilter,但如果我包含排除的PTORequestIds 并省略filterOptions,则ImportPTOByIds 被选中。

我倾向于认为由模型绑定器处理的列表和数组与模型绑定的其他默认 CLR 类型(字符串、int、Guid 等)具有不同的行为。

虽然字符串是必需的并且会抛出 404 或解析到其他路由,但不需要在请求中明确定义数组。

可以安全地假设,从 WebApi 进行路由解析的其他规则是什么。

【问题讨论】:

    标签: c# arrays asp.net-web-api custom-model-binder


    【解决方案1】:

    当您包含 filterOptions 时,它会解析为 ImportPTOByFilter,因为其他路由没有过滤器选项参数。

    如果您删除过滤器选项,它会解析为 ImportPTOByIds,因为参数与方法签名匹配。路由解析将通过路由名称和参数进行。如果你有

    RouteA(string myString, int myInt) {...}
    

    RouteA(string myString) {...}
    

    RouteA(int myInt) {...}
    

    它将根据您是否传递字符串、int 或两者来解析路由。

    比我更有知识的其他人可能会添加更多信息,但我认为您想制作一个实际模型,以封装整个请求的方式,您拥有一种方法,并在该方法中检查模型以确定是否应该过滤或不是。

    【讨论】:

    • 参数不匹配一个数组被称为excludedPTORequestIds,另一个被称为ptoRequestIds,在两个路由中它们都缺少1个参数。在这两个 Senarios 中,它们都缺少 1 个参数。但是取决于缺少的参数是如何解析路由
    • 数据类型确实如此。这就是为什么大多数最佳实践都说不要有两个同名的路由编辑:通过删除过滤字符串参数,您可以使签名匹配第一个路由。
    • 我同意,名称不应该重复,我只是想了解模型绑定器实现,因为此代码导致了基于客户端如何序列化获取 url 的错误。我只是看看是否还有其他需要注意的问题
    • 我明白了,如果你在启动时使用标准的 webapiconfig 类,我认为 modelbinder 首先验证控制器和操作,然后它会查看参数的数量和类型。在您的情况下,从查询字符串中删除 filterOptions 将使未过滤的操作与过滤后的操作更接近地匹配 url,无论您为参数提供什么名称
    • 我做了一点挖掘,下面问题的第二个答案说 API 模型绑定与 MVC 模型绑定不同,您必须使用具有数据注释属性的自定义绑定器才能使其工作使用 FromURI stackoverflow.com/questions/26600275/… 不幸的是,我不确定这是否对您有帮助,因为我总是使用数据注释,我想我从来没有遇到过完全相同的情况,但我的直觉是它没有有一个完全匹配,所以它是按数据类型来的。
    猜你喜欢
    • 2019-09-24
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    相关资源
    最近更新 更多