【问题标题】:WebApi: mapping parameter to header valueWebApi:将参数映射到标头值
【发布时间】:2014-01-04 07:33:18
【问题描述】:

我已经做了一些搜索,但似乎没有找到任何东西......

使用 WebApi,我想将输入参数映射到标头值:例如

例如在控制器中:

public User GetUser(int id){
   ...
   return user;
}

我希望 WebApi 将 id 参数映射到标头值(例如 X-Auth: 1234)...而不是 URL 参数。

支持吗?

【问题讨论】:

    标签: asp.net asp.net-web-api asp.net-web-api-routing


    【解决方案1】:

    DotNet Core 上的 WebApi 具有一些用于从请求中提取数据的附加属性。 Microsoft.AspNetCore.Mvc.FromHeaderAttribute 将从请求头中读取。

    public ActionResult ReadFromHeader([FromHeader(Name = "your-header-property-name")] string data){
       //Do something
    }
    

    【讨论】:

      【解决方案2】:

      感谢 filipov 的回答。我接受了您的代码并对其进行了一些修改以满足我的需要。我在这里发布我的更改,以防任何人都可以使用它。

      我做了 2 处更改。

      1. 我喜欢 FromHeaderAttribute 的想法,但没有子类化。我公开了这个类,并要求用户设置参数名称。

      2. 我需要支持除字符串之外的其他数据类型。所以我尝试将字符串值转换为描述符的参数类型。

      像这样使用它:

      [HttpGet]
      public void DeleteWidget(long widgetId, [FromHeader("widgetVersion")] int version)
      {
          ... 
      }
      

      这是我的 FromHeaderBinding

      public class FromHeaderBinding : HttpParameterBinding
      {
          private readonly string _name;
      
          public FromHeaderBinding(HttpParameterDescriptor parameter, string headerName)
              : base(parameter)
          {
              if (string.IsNullOrEmpty(headerName)) throw new ArgumentNullException("headerName");
              _name = headerName;
          }
      
          public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
          {
              IEnumerable<string> values;
              if (actionContext.Request.Headers.TryGetValues(_name, out values))
              {
                  var tempVal = values.FirstOrDefault();
                  if (tempVal != null)
                  {
                      var actionValue = Convert.ChangeType(tempVal, Descriptor.ParameterType);
                      actionContext.ActionArguments[Descriptor.ParameterName] = actionValue;
                  }
              }
      
              var taskSource = new TaskCompletionSource<object>();
              taskSource.SetResult(null);
              return taskSource.Task;
          }
      }
      

      【讨论】:

        【解决方案3】:

        我不认为这是开箱即用的支持,例如 [FromBody] 属性。 如here 所述,您似乎应该能够通过使用模型绑定器来实现此功能。在模型绑定器中,您可以访问请求及其标头,因此您应该能够读取标头并将其值设置为 bindingContext.Model 属性。

        编辑:进一步阅读文章,似乎自定义 HttpParameterBinding 和 ParameterBindingAttribute 是更合适的解决方案,或者至少我会这样做。您可以实现一个通用的 [FromHeader] 属性来完成这项工作。我也在与同样的问题作斗争,所以一旦我找到解决方案,我会发布它。

        编辑 2:这是我的实现:

        public class FromHeaderBinding : HttpParameterBinding
        {
            private string name;
        
            public FromHeaderBinding(HttpParameterDescriptor parameter, string headerName) 
                : base(parameter)
            {
                if (string.IsNullOrEmpty(headerName))
                {
                    throw new ArgumentNullException("headerName");
                }
        
                this.name = headerName;
            }
        
            public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
            {
                IEnumerable<string> values;
                if (actionContext.Request.Headers.TryGetValues(this.name, out values))
                {
                    actionContext.ActionArguments[this.Descriptor.ParameterName] = values.FirstOrDefault();
                }
        
                var taskSource = new TaskCompletionSource<object>();
                taskSource.SetResult(null);
                return taskSource.Task;
            }
        }
        
        public abstract class FromHeaderAttribute : ParameterBindingAttribute
        {
            private string name;
        
            public FromHeaderAttribute(string headerName)
            {
                this.name = headerName;
            }
        
            public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
            {
                return new FromHeaderBinding(parameter, this.name);
            }
        }
        
        public class MyHeaderAttribute : FromHeaderAttribute
        {
            public MyHeaderAttribute()
                : base("MyHeaderName")
            {
            }
        }
        

        那么你可以这样使用它:

        [HttpGet]
        public IHttpActionResult GetItem([MyHeader] string headerValue)
        {
            ...
        }
        

        希望对您有所帮助。

        【讨论】:

        • 这正是我想要的。谢谢。
        • [FromHeader("MyHeader")] 是否也适用于您的代码?
        • 是的,但我猜这在 2013 年不存在。 @ChristianKuetbach
        猜你喜欢
        • 1970-01-01
        • 2013-10-13
        • 2017-10-13
        • 1970-01-01
        • 2015-10-21
        • 1970-01-01
        • 2020-08-09
        • 2019-05-26
        • 1970-01-01
        相关资源
        最近更新 更多