更改参数名称Web Api模型绑定

时间:2014-10-28 03:08:23

标签: c# asp.net-web-api model-binding

我正在使用Web API模型绑定来解析来自URL的查询参数。例如,这是一个模型类:

public class QueryParameters
{
    [Required]
    public string Cap { get; set; }

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

当我拨打/api/values/5?cap=somecap&id=1之类的内容时,此功能正常。

我是否可以通过某种方式更改模型类中属性的名称,但保持查询参数名称相同 - 例如:

public class QueryParameters
{
    [Required]
    public string Capability { get; set; }

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

我认为将[Display(Name="cap")]添加到Capability属性会起作用,但事实并非如此。我应该使用某种类型的数据注释吗?

控制器的方法如下:

public IHttpActionResult GetValue([FromUri]QueryParameters param)    
{
    // Do Something with param.Cap and param.id
}

4 个答案:

答案 0 :(得分:20)

您可以使用FromUri绑定属性的Name属性将查询字符串参数用于方法参数的不同名称。

如果您传递简单参数而不是QueryParameters类型,则可以绑定如下值:

/api/values/5?cap=somecap&id=1

public IHttpActionResult GetValue([FromUri(Name = "cap")] string capabilities, int id)    
{
}

答案 1 :(得分:11)

Web API使用与ASP.NET MVC不同的模型绑定机制。它使用格式化程序在主体中传递的数据和模型绑定器中查询字符串中传递的数据(如您的情况)。格式化程序遵循其他元数据属性,而模型绑定程序则不然。

因此,如果您在消息正文中传递模型而不是查询字符串,则可以按如下方式对数据进行注释,它可以正常工作:

public class QueryParameters
{
    [DataMember(Name="Cap")]
    public string Capability { get; set; }

    public string Id { get; set; }
}

你可能已经知道了。要使它与查询字符串参数一起使用并因此模型绑定器,您必须使用自己的自定义模型绑定器来实际检查和使用DataMember属性。

下面这段代码可以解决问题(尽管它远非生产质量):

public class MemberModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var model = Activator.CreateInstance(bindingContext.ModelType);
        foreach (var prop in bindingContext.PropertyMetadata)
        {
            // Retrieving attribute
            var attr = bindingContext.ModelType.GetProperty(prop.Key)
                                     .GetCustomAttributes(false)
                                     .OfType<DataMemberAttribute>()
                                     .FirstOrDefault();
            // Overwriting name if attribute present
            var qsParam = (attr != null) ? attr.Name : prop.Key;
            // Setting value of model property based on query string value
            var value = bindingContext.ValueProvider.GetValue(qsParam).AttemptedValue;
            var property = bindingContext.ModelType.GetProperty(prop.Key);
            property.SetValue(model, value);
        }
        bindingContext.Model = model;
        return true;
    }
}

您还需要在控制器方法中指明您要使用此模型绑定器:

public IHttpActionResult GetValue([ModelBinder(typeof(MemberModelBinder))]QueryParameters param)

答案 2 :(得分:0)

我花了几个小时研究一个针对同一问题的强大解决方案,当一个班轮就可以解决这个问题:

myModel.Capability = HttpContext.Current.Request["cap"];

答案 3 :(得分:0)

我刚碰到这个并在我的参数类中使用了一个getter来返回绑定属性。

所以在你的例子中:

public class QueryParameters
{
    public string cap {get; set;}
    public string Capability
    {
      get { return cap; }
    }

    public string Id { get; set; }
}

现在,您可以在Controller中引用Capability属性。

public IHttpActionResult GetValue([FromUri]QueryParameters param)    
{
    // Do Something with param.Capability,
    // except assign it a new value because it's only a getter
}

当然,如果您对param对象使用反射或序列化它,则会包含cap属性。不知道为什么有人会需要使用查询参数。