繁体   English   中英

Web API请求对象中的强类型AND任意属性

[英]Strongly typed AND arbitrary properties in Web API request object

我有一个看起来很像这样的对象:

public class MyNiceRequest 
{
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }

    public string SomeOptionalField { get; set; }
}

我的控制器看起来像下面的,仍然很标准:

public MyNiceResponse Post(MyNiceRequest request) {
...
}

从调用应用程序的前端,我想包括比对象中指定的三个更多的字段。 这些字段是在运行时生成的(通过管理界面控制),因此我无法将其应用于我的请求类。 但是,我还没有找到在控制器中检索它们的好方法。

我可以使我的请求对象( MyNiceRequest )从Dictionary<string,string>继承-然后将它们全部获取,但它们将不会绑定到强类型类的各自属性上(似乎像Dictionary之前绑定了其余部分使用任何模型活页夹)。 另外,更重要的是,验证(对应用程序至关重要)将停止工作。

我已经看到了这个问题,但是它没有给我任何东西,因为Request.Content.Read...方法给了我空的结果(因为它已经被读取并绑定到模型了?)。

假设我要从前端输入以下字段:

  • FirstName (应绑定到强类型,无其他地方)
  • LastName (应绑定到强类型,无其他地方)
  • SomeOptionalField (应绑定到强类型,无处可)
  • RuntimeGenerated1 (应该在字典中结束)
  • RuntimeGenerated2 (应该在字典中结束)

我想要以下两种解决方案之一:

  • 可以从Dictionary<string,string>继承,但是让字典在强类型属性之后绑定,以使验证工作
  • MyNiceRequest上具有一个单独的属性,该属性可能类似于Dictionary<string,string> TheRest { get; set; } Dictionary<string,string> TheRest { get; set; } Dictionary<string,string> TheRest { get; set; }并将其绑定到其余的传入属性。

重写前端以将运行时生成的字段作为单独的集合传递是不可行的。

..这是否可以通过重新使用/重新排序现有内容来实现,还是我必须从头开始编写完整的媒体类型格式化程序和/或模型绑定程序?

对于application/json内容类型,可以将DynamicObject与WebAPI的默认JSON格式化程序一起使用。

public class MyNiceRequest : DynamicObject
{
    private Dictionary<string, string> _dynamicMembers = new Dictionary<string, string>();

    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }

    public string SomeOptionalField { get; set; }

    [JsonIgnore]
    public Dictionary<string, string> DynamicMembers
    {
        get { return _dynamicMembers; }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object value)
    {
        string stringValue;
        var isFound = _dynamicMembers.TryGetValue(binder.Name, out stringValue);
        value = stringValue;
        return isFound;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (value is string)
        {
            _dynamicMembers[binder.Name] = (string)value;
            return true;
        }
        return false;
    }
}

编辑

  1. 如果希望对象以相同的格式序列化,请实现IDictionary<string, string> 这很简单,只需将接口实现委派给_dynamicMembers

  2. 此解决方案不适用于默认的XML和x-www-form-urlencoded格式化程序:(

您可以拥有这样的DTO。

public class MyNiceRequest
{
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }

    public string SomeOptionalField { get; set; }

    public Dictionary<string, string> TheRest { get; set; }
}

如果在请求正文中发布JSON,例如{"firstname":"arve", "therest":{"key":"value"}} ,则将填充FirstName属性。 TheRest将具有一个带有键“ key”和值“ value”的项目。 当然,由于JSON不包含LastName ,因此ModelState.IsValid将为false

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM