如何替换 Web API 模型绑定的行为,以便在没有传入参数时收到一个新实例而不是 Null

2024-01-01

我们有一个包含许多操作的 API,这些操作需要Filter目的。但是,当有人调用 API 方法并且不传递任何参数时,我们最终会得到空引用。为了避免在任何地方都必须检查这一点,我们希望改变模型绑定的行为,以便对于该类型它返回一个新实例而不是 null。

此外,我们真的不想为过滤器类型编写自己的活页夹,因为它可能会经常更改。

我们找到了一种机制,可以让我们写一个模型绑定器参数绑定 http://msdn.microsoft.com/en-us/library/system.web.http.modelbinding.modelbinderparameterbinding(v=vs.118).aspx但后来我不知道如何将该项目添加到 WebAPI 配置中。

那么,我们是否尝试了正确的方法?如果是,我们如何告诉 WebAPI 使用新的参数绑定?

作为参考,这里是 ModelParameterBindingModel...我绝对不确定这是生产代码!因为我无法运行或测试它:)

public class QueryFilterModelBinderParameterBinding : ModelBinderParameterBinding
    {
        private readonly ValueProviderFactory[] _valueProviderFactories;
       private readonly IModelBinder _binder;

       public QueryFilterModelBinderParameterBinding(HttpParameterDescriptor descriptor,
           IModelBinder modelBinder,
           IEnumerable<ValueProviderFactory> valueProviderFactories)
           : base(descriptor, modelBinder, valueProviderFactories)
       {
           if (modelBinder == null)
           {
               throw new ArgumentNullException("modelBinder");
           }
           if (valueProviderFactories == null)
           {
               throw new ArgumentNullException("valueProviderFactories");
           }

           _binder = modelBinder;
           _valueProviderFactories = valueProviderFactories.ToArray();
       }

       public new IEnumerable<ValueProviderFactory> ValueProviderFactories
       {
           get { return _valueProviderFactories; }
       }

       public new IModelBinder Binder
       {
           get { return _binder; }
       }

       public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
       {
           var ctx = GetModelBindingContext(metadataProvider, actionContext);

           var haveResult = _binder.BindModel(actionContext, ctx);
           //here's where we instantiate an empty filter if we cannot bind one
           var model = haveResult ? ctx.Model : new QueryFilter();
           SetValue(actionContext, model);

           return Task.FromResult(model);
       }

       private ModelBindingContext GetModelBindingContext(ModelMetadataProvider metadataProvider, HttpActionContext actionContext)
       {
           var name = Descriptor.ParameterName;
           var type = Descriptor.ParameterType;

           var prefix = Descriptor.Prefix;

           var vp = new CompositeValueProviderFactory(_valueProviderFactories).GetValueProvider(actionContext);

           var ctx = new ModelBindingContext()
           {
               ModelName = prefix ?? name,
               FallbackToEmptyPrefix = prefix == null, // only fall back if prefix not specified
               ModelMetadata = metadataProvider.GetMetadataForType(null, type),
               ModelState = actionContext.ModelState,
               ValueProvider = vp
           };

           return ctx;
       }
    }

因此,我设法以稍微不同的方式解决了这个问题。尽管我仍然有兴趣看看是否有更惯用的方法来解决这个问题!

首先我们创建一个 HttpParameterBinding

public class QueryFilterParameterBinding : HttpParameterBinding
{
    private readonly HttpParameterBinding _modelBinding;
    //private readonly HttpParameterBinding _formatterBinding;

    public QueryFilterParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor)
    {
        _modelBinding = new ModelBinderAttribute().GetBinding(descriptor);
        //_formatterBinding = new FromBodyAttribute().GetBinding(descriptor);
    }

    public override async Task ExecuteBindingAsync(
        ModelMetadataProvider metadataProvider, 
        HttpActionContext actionContext,
        CancellationToken cancellationToken)
    {
        await _modelBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
        var queryFilter = GetValue(actionContext) as QueryFilter;
        if (queryFilter == null)
        {
            queryFilter = new QueryFilter();
            SetValue(actionContext, queryFilter);
        }
    }
}

并在WebApiConfig类中添加一个方法

//returning null here tells another binding or the default binding to handle this request
private static HttpParameterBinding GetQueryFilterBinding(HttpParameterDescriptor descriptor)
{
    return descriptor.ParameterType == typeof (QueryFilter) 
        ? new QueryFilterParameterBinding(descriptor) 
        : null;
}

在 WebApiConfig.Configure 方法中我们调用:

config.ParameterBindingRules.Add(typeof(QueryFilter), GetQueryFilterBinding)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何替换 Web API 模型绑定的行为,以便在没有传入参数时收到一个新实例而不是 Null 的相关文章

  • 实体框架 - sql server 表中未设置默认值

    SQL Server 2005 数据库表有一列 createdon 其默认值设置为 getdate 我正在尝试使用实体框架添加记录 createdon 列未更新 我是否错过了实体框架中的任何属性 请提出建议 这是实体框架存在的少数问题之一
  • 管理多个解决方案中存在的 C# 项目的 Nuget 包

    我现在正处于这样的阶段重构疯狂一个有很多的大项目遗留和不稳定的模块 我决定拆分解决方案目前 所有项目 大约有 20 个 而且由于下个月肯定会出现单元测试项目 还会有更多 链接在一起 使其更加独立和细化 通过这种方法 有一些模块 例如需要在多
  • 轮廓积分算法 C++

    我正在尝试编写一个应用数学程序来计算复平面中的轮廓积分 对于初学者来说 我想为梯形方法编写一个算法 但我有点坚持理解它会是什么样子 毕竟 我们通常将梯形方法视为 2D 图 而这里我们有 f C gt C 所以我们谈论的是 4D 最终我希望用
  • C# 委托实例化与仅传递方法引用 [重复]

    这个问题在这里已经有答案了 我有一个简单的问题 与仅传递函数引用相比 实例化 C 委托有什么优势 我的意思是 Why do Thread t new Thread new ThreadStart SomeObject SomeMethod
  • 类型定义存在于两个库中

    我正在使用 NET 4 5 构建 ASP NET Web 窗体网站 错误 The type System ComponentModel DataAnnotations Schema ForeignKeyAttribute exists in
  • 使用 boost::asio 是否有一种可移植的方法来查找空闲端口号

    我目前正在尝试找出一种方法来查找空闲端口号以建立连接 最好使用 boost asio 然后 该端口号将用于侦听 只有这样我才能打开套接字 大致来说 有没有办法做到 tcp resolver query query localhost por
  • 带有 Prism 区域适配器的 AvalonDock

    我看到了一些关于 SO 的问题 但似乎没有一个适合我 我希望能够使用伟大的使用 Prism 4 但是 所有示例区域适配器均适用于 Avalondock 1 x 系列 我无法使其工作 有人有关于如何为 AvalonDock 的 LayoutD
  • C# 中 value 为匿名类型的字典

    是否可以在 C 中创建一个System Collections Generic Dictionary
  • boost变体简单调用常用方法

    我有两个指针 只能设置其中之一 所以我正在考虑使用 boost variant 例如 boost variant
  • 在 .NET Core 上通过 MEF 将参数传递给插件构造函数?

    我花了几个小时试图弄清楚如何通过 MEF System Composition 将参数传递给插件构造函数 但一切都无济于事 不用说 相关文档很少 查看源代码也没有帮助 这曾经非常容易做到 使用 CompositionHost Compose
  • 将私有部分保留在 C++ 标头之外:纯虚拟基类与 pimpl

    我最近从 Java 和 Ruby 切换回 C 令我惊讶的是 当我更改私有方法的方法签名时 我必须重新编译使用公共接口的文件 因为私有部分也位于 h 文件中 我很快想出了一个解决方案 我想这对于 Java 程序员来说是典型的 接口 纯虚拟基类
  • 向量和常量

    考虑一下这个 void f vector
  • 创建 PING 程序时限制 ICMP 回显答复

    我正在编写一个多线程 ping 程序 我在每个线程 针对每个 IP 上创建了原始套接字 并使用 sendto 向每个线程发送了 ICMP Echo 请求 然后在每个线程中执行了 receivevfrom 我正在从各种套接字中的 IP 获取消
  • 我使用 tm/mktime 是否错误,如果没有,有解决方法吗?

    我认为下面的程序应该输出从公元 1 年到 1970 年每年第一天到 1970 年的秒数 前面是time t在编译它的系统上 CHAR BIT是一个宏 所以我认为你不能只是复制编译后的可执行文件并假设它是正确的 尽管实际上一切都使用 8 位c
  • 使用 c++20 范围删除最后一个元素的最佳方法是什么

    有没有比反转两次更好的方法来使用 c 20 范围删除容器中的最后一个元素 include
  • System.IndexOutOfRangeException:索引超出了数组的范围[重复]

    这个问题在这里已经有答案了 我正在开发一个 ATM 软件作为家庭作业 我想知道今天处理的交易总量 为此我编写了以下代码 public decimal getDayTransaction int accountid string date s
  • 隐式类型转换 - 编译器错误

    这个问题与this https stackoverflow com questions 3529449 can i make the ternary operator treat my class like a bool问题 下面的代码在V
  • 以编程方式连接和断开 USB,“无需拔出和重新插入”

    我需要以编程方式连接和断开 USB 也就是说 我已经插入了USB设备 我需要使用 C NET 应用程序传输文件 该应用程序将监视特定文件夹并将文件从该文件夹传输到 USB 驱动器 我需要在文件传输后断开 USB 设备的连接 并在需要时连接
  • C++ 从文件中读取字符串

    我试图将字符串直接存储到一个文件中 以便稍后在 C 中读取 基本上 对于整个范围 我试图将带有字符串变量的对象数组存储在文件中 并且这些字符串变量将通过类似 object 的内容读取 0 字符串 然而 每次我尝试读取字符串变量时 系统都会给
  • 文件按文件名模式存在

    我在用 File Exists filepath 我想做的是将其替换为模式 因为文件名的第一部分发生了变化 例如 该文件可以是 01 peach xml 02 peach xml 03 peach xml 如何根据某种搜索模式检查文件是否存

随机推荐

  • Netflix 如何在不刷新页面且无需 JavaScript 的情况下提交评分?

    我正在尝试为我的网站做一些类似 Netflix 的 5 星级评级系统的事情 我注意到 Netflix 即使禁用了 JavaScript 仍然会在不刷新页面的情况下提交评级 这是显而易见的 因为当您手动重新加载页面时 您可以看到新的评级 但是
  • React-navigation 在调试模式下工作正常,但在发布模式下不行

    几周以来我遇到了一个问题 我在我的react native应用程序中使用react navigation 当我在调试模式下在我的设备上测试时 我在屏幕之间正确导航 但是当我构建签名的apk时 导航不再工作 我尝试了一切 但没有任何效果 我正
  • 在已知缺失时间间隔之间插入 3D 坐标

    数据是空间中的路径 我有 3D 位置数据 x y z 和记录位置点的时间 x y 和 z 坐标是物体在 3D 空间中移动的点位置 时间值是记录每个点的时间 从 0 开始 x y z time s 0 1 2 2 3 3 0 2 4 2 4
  • 为什么不在java中使用带有锁的try?

    我读了这个话题 https stackoverflow com questions 6965731 are locks autocloseable 和这个博客文章 http www java7developer com blog p 256
  • 编译时出现错误?

    当我编译代码时 我收到这些错误 我有 user include 下的所有标题 g Ip appmanager inc Icore inc p appmanager src appmanager process cpp o p appmana
  • 本地主机上的 404 错误

    我正在尝试使用一些ajax 来发送一些电子邮件 我在使用冷聚变之前已经这样做过并且没有任何问题 我遇到的是本地主机未在目录中找到明确的文件 事实上 该文件与index php 位于同一目录中 这没有发现任何问题 然而它给了我一个404错误找
  • 使用 LiveData、协程和事务测试 Android Room

    我想测试我的数据库层 但我陷入了第 22 条军规类型的情况 测试用例由两部分组成 保存一些实体 加载实体并断言数据库映射按预期工作 简而言之 问题在于 Insert is a suspend方法 这意味着它需要运行在runBlocking
  • Eclipse“正确缩进”忽略空格与制表符设置

    我正在 Windows 中运行 Eclipse Juno Service Release 2 20130225 0426 我发现自动缩进 Ctrl I 会忽略常规 编辑器 文本编辑器 插入选项卡空格和 Java 代码样式 格式化程序 缩进
  • “无处不在”使用 LINQ 时的性能问题?

    升级到 ReSharper5 后 它为我提供了更多关于代码改进的有用提示 我现在随处看到的一个提示是用 LINQ 查询替换 foreach 语句 举个例子 private Ninja FindNinjaById int ninjaId fo
  • 获取 Android 上的应用程序安装日期

    有没有办法找出 Android 设备上的 应用程序安装日期 进行了大量搜索 但无法找到相关答案 无法找到有关应用程序安装日期的任何信息PackageManager文档 代码 或这个 API 级别 9向上 long installed con
  • Z Shell“自动加载”内置 - 它有什么好处?

    我已经使用 Z shell 一段时间了 我开始感到好奇 我在编写自己的函数时偶然发现的一件事是 自动加载 根据 zshbuiltins 1 手册页autoload是 相当于functions u 有一个例外 它 相当于typeset f 有
  • Webkit 必须始终在主线程上使用吗?

    我试图在后台渲染网页 但遇到了以下麻烦 2012 05 11 12 39 02 086 77207 1c03 An uncaught exception was raised 2012 05 11 12 39 02 087 77207 1c
  • 在从代码库中的 dockerfile 构建的 Docker 容器中运行 Jenkins 测试

    我想部署一个基于Jenkins的持续集成平台 由于我有各种类型的项目 PHP Symfony node Angular 等 并且我希望这些测试既可以在本地运行 也可以在 Jenkins 上运行 所以我正在考虑使用 Docker 容器 我的目
  • 数据库内部结构 - 从哪里开始? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 假设您想了解一些有关数据库内部结构的知识 最好看的源代码是什么 最好买的书 前几天我和一个朋友讨论这个问
  • 构建 Qt5 Git / Perl - 路径

    我的理解能力有点问题 In the Qt Wiki http qt project org wiki Building Qt 5 from Git aea23489ce3aa9b6406ebb28e0cda430上面写着我必须 Hint 确
  • 如何将 Delphi 调试器附加到 64 位 IIS 7.5?

    我在 Windows 7 Pro 64 和 IIS 7 5 上运行 Delphi XE 开发 ISAPI 应用程序 IIS 配置正确 包括允许 32 位代码在 ISAPI 进程中运行 ISAPI进程运行正常 在 Delphi 中 我尝试附加
  • Chrome Inspect - 关闭预览框架

    在 Chrome 的最新更新中 检查 窗口 chrome inspect 有一个预览窗口 在屏幕移动框架中显示网页 我该如何关闭它 到目前为止 我所做的最接近的事情是减少宽度 这样它就不会占用太多的屏幕空间 图片示例 您可以使用下面突出显示
  • Docker 镜像 - 类型。修身 vs 修身弹力 vs 弹力 vs 高山

    我正在寻找一个 docker 镜像来构建一个 java 应用程序 并查看可用的 OpenJDK 镜像的变体 我正在看这里https github com docker library openjdk tree master 8 jdk ht
  • 如何正确地使JSP会话失效?

    所以问题就在这里 当用户退出我的网站时 他们仍然可以点击后退按钮并继续使用该网站 为了跟踪用户是否登录 我创建了一个会话属性 isActive 该属性在用户登录时设置为 true 并在注销时会话失效之前被 冗余 删除 另外 我在每个页面上检
  • 如何替换 Web API 模型绑定的行为,以便在没有传入参数时收到一个新实例而不是 Null

    我们有一个包含许多操作的 API 这些操作需要Filter目的 但是 当有人调用 API 方法并且不传递任何参数时 我们最终会得到空引用 为了避免在任何地方都必须检查这一点 我们希望改变模型绑定的行为 以便对于该类型它返回一个新实例而不是