ASP.Net Web API 自定义模型与 x-www-form-urlencoded 发布的数据绑定 - 似乎没有任何效果

2024-01-12

我在发布时很难让自定义模型绑定正常工作x-www-form-urlencoded数据。我已经尝试了所有我能想到的方法,但似乎没有任何方法能产生预期的结果。请注意,发布 JSON 数据时,我的 JsonConverters 等都工作正常。当我发帖时x-www-form-urlencoded系统似乎无法弄清楚如何绑定我的模型。

我的测试用例是我想绑定一个 TimeZoneInfo 对象作为我的模型的一部分。

这是我的模型活页夹:

public class TimeZoneModelBinder : SystemizerModelBinder
{
    protected override object BindModel(string attemptedValue, Action<string> addModelError)
    {
        try
        {
            return TimeZoneInfo.FindSystemTimeZoneById(attemptedValue);
        }
        catch(TimeZoneNotFoundException)
        {
            addModelError("The value was not a valid time zone ID. See the GetSupportedTimeZones Api call for a list of valid time zone IDs.");
            return null;
        }
    }
}

这是我正在使用的基类:

public abstract class SystemizerModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var name = GetModelName(bindingContext.ModelName);
        var valueProviderResult = bindingContext.ValueProvider.GetValue(name);
        if(valueProviderResult == null || string.IsNullOrWhiteSpace(valueProviderResult.AttemptedValue))
            return false;

        var success = true;
        var value = BindModel(valueProviderResult.AttemptedValue, s =>
        {
            success = false;
            bindingContext.ModelState.AddModelError(name, s);
        });
        bindingContext.Model = value;
        bindingContext.ModelState.SetModelValue(name, new System.Web.Http.ValueProviders.ValueProviderResult(value, valueProviderResult.AttemptedValue, valueProviderResult.Culture));
        return success;
    }

    private string GetModelName(string name)
    {
        var n = name.LastIndexOf(".", StringComparison.Ordinal);
        return n < 0 || n >= name.Length - 1 ? name : name.Substring(n + 1);
    }

    protected abstract object BindModel(string attemptedValue, Action<string> addModelError);
}

我使用这样的基类来简化创建其他自定义模型绑定程序的过程。

这是我的模型活页夹提供商。请注意,这是从我的 IoC 容器中正确调用的,因此我不会费心去展示我的代码的这方面。

public class SystemizerModelBinderProvider : ModelBinderProvider
{
    public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
    {
        if(modelType == typeof(TimeZoneInfo))
            return new TimeZoneModelBinder();

        return null;
    }
}

最后,这是操作方法和模型类:

[DataContract)]
public class TestModel
{
    [DataMember]
    public TimeZoneInfo TimeZone { get; set; }
}

[HttpPost]
public HttpResponseMessage Test(TestModel model)
{
    return Request.CreateResponse(HttpStatusCode.OK, model);
}

对于操作方法,我尝试过:

public HttpResponseMessage Test([FromBody] TestModel model)

这会调用FormUrlEncodedMediaFormatter,这似乎完全忽略了我的自定义模型绑定器。

public HttpResponseMessage Test([ModelBinder] TestModel model)

正如预期的那样,这会调用我的自定义模型绑定器,但它只提供 ValueProvidersRouteData and QueryString并且由于某种原因不提供任何内容。见下文:

我也尝试过用以下方式装饰班级本身ModelBinder(typeof(SystemizerModelBinderProvider))

为什么模型绑定仅在我使用 [ModelBinder] 属性时发生,为什么它仅尝试读取路由和查询字符串值并忽略正文内容?为什么FromBody忽略我的自定义模型绑定器提供程序?

如何创建一个可以接收 POSTED 的场景x-www-form-urlencoded数据并使用自定义逻辑成功绑定模型属性?


我建议您阅读following blog post http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx其中 Mike Stall 详细解释了模型绑定在 Web API 中的工作原理:

有两种绑定参数的技术:模型绑定和 格式化程序。在实践中,WebAPI 使用模型绑定来读取 从正文中读取的查询字符串和格式化程序。

以下是确定是否读取参数的基本规则 模型绑定或格式化程序:

  1. 如果参数没有属性,则做出决定 纯粹取决于参数的 .NET 类型。 “简单类型”使用模型 捆绑。复杂类型使用格式化程序。 “简单类型”包括: 基元、TimeSpan、DateTime、Guid、Decimal、String 等 使用从字符串转换的 TypeConverter。
  2. 您可以使用[FromBody]属性来指定应该从 身体。
  3. 您可以使用[ModelBinder]参数上的属性或 参数的类型指定参数应该是模型绑定的。 此属性还允许您配置模型绑定器。[FromUri]是 的派生实例[ModelBinder]专门配置了一个 模型绑定器仅查看 URI。
  4. 正文只能读取一次。 因此,如果签名中有 2 种复杂类型,则至少其中一种 必须具有 [ModelBinder] 属性。

因此,如果数据源是请求正文,那么您可以创建自定义 MediaTypeFormatter 而不是模型绑定器。

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

ASP.Net Web API 自定义模型与 x-www-form-urlencoded 发布的数据绑定 - 似乎没有任何效果 的相关文章

  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐