【问题标题】:How to bind a property to a complex object using WebApi and a custom value binder?如何使用 WebApi 和自定义值绑定器将属性绑定到复杂对象?
【发布时间】:2016-11-10 21:18:15
【问题描述】:

我有不同的 Web API 控制器,它们使用声明进行保护。因此,在我的控制器中,我使用的是 asp.net Identity,而 User.Identity 的类型是 ClaimsIdentity。

其中一个声明是登录到应用程序的当前 userId。

例如,当我发布一个复杂的对象(例如 Order)并且该 Order 具有如下示例所示的属性 UserId 时,我希望该属性由声明中的值填充。

class Order
{
  public int Quantity { get; set; }
  public int ProductId { get; set; }
  public int UserId { get; set; }
}

class OrdersController : BaseApiController 
{
  [HttpPost]
  public IHttpActionResult Post(Order order)
  {
    // do something
    return Ok();
  }
}

所以,我想要的是让 Quantity 和 ProducId 属性填充来自请求正文的值,以及来自 Claims 的 UserId。

我尝试创建一个自定义值提供程序,如下所示:

public class IdentityClaimsValueProvider : IValueProvider
{
    private readonly Dictionary<string, string> _claims;
    private readonly string[] _claimsKeys;

    public IdentityClaimsValueProvider(Dictionary<string, string> claims)
    {
        _claims = claims;
        _claimsKeys = claims.Keys.ToArray();
    }

    public bool ContainsPrefix(string prefix)
    {
        if (prefix == null)
            throw new ArgumentNullException(nameof(prefix));

        return _claimsKeys.Any(x => prefix.Equals(x, StringComparison.OrdinalIgnoreCase));
    }

    public ValueProviderResult GetValue(string key)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));

        var claim = _claimsKeys.FirstOrDefault(x => key.Equals(x, StringComparison.OrdinalIgnoreCase));
        if (claim != null && _claims[claim] != null)
        {
            return new ValueProviderResult(_claims[claim], _claims[claim], CultureInfo.CurrentCulture);
        }

        return null;
    }
}

public class IdentityClaimsValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(HttpActionContext actionContext)
    {
        var controller = actionContext.ControllerContext.Controller as WebApiBaseController;
        if (controller == null)
            return null;

        var claims = controller.GetUserIdentity().Claims;

        var claimsValues = new Dictionary<string, string>
        {
            { "userId", claims.First(x => x.Type == Common.Constants.ClaimTypes.USER_ID).Value }
        };

        return new IdentityClaimsValueProvider(claimsValues);
    }
}

我也将此添加到我的配置中:

config.Services.Add(typeof(ValueProviderFactory), new IdentityClaimsValueProviderFactory());

但这不起作用。当我发帖时,我填写了 Quantity 和 ProductId 属性,但没有填写 UserId

【问题讨论】:

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


    【解决方案1】:

    您必须通过以下方式更改操作的签名:

    public IHttpActionResult Post([ValueProvider(typeof(IdentityClaimsValueProviderFactory))]string userId, Order order)
    

    如果你想在 order 属性中有 useId 的值,你必须改变类IdentityClaimsValueProviderFactory

    问候。

    【讨论】:

      猜你喜欢
      • 2016-09-13
      • 2016-04-02
      • 2011-11-06
      • 2011-02-28
      • 2011-08-22
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 2013-10-09
      相关资源
      最近更新 更多