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
}
_
FromUriバインディング属性のNameプロパティを使用して、メソッド引数とは異なる名前のクエリ文字列パラメーターを使用できます。
QueryParameters
型ではなく単純なパラメーターを渡す場合は、次のように値をバインドできます。
/api/values/5?cap=somecap&id=1
public IHttpActionResult GetValue([FromUri(Name = "cap")] string capabilities, int id)
{
}
Web APIは、ASP.NETMVCとは少し異なるメカニズムをモデルバインディングに使用します。本文に渡されるデータにはフォーマッターを使用し、クエリ文字列に渡されるデータにはモデルバインダーを使用します(あなたの場合のように)。フォーマッターは追加のメタデータ属性を尊重しますが、モデルバインダーは尊重しません。
したがって、クエリ文字列ではなくメッセージ本文でモデルを渡した場合、次のようにデータに注釈を付けることができ、それは機能します。
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)
私はこれに遭遇し、パラメータクラスでゲッターを使用してバインドされたプロパティを返しました。
だからあなたの例では:
public class QueryParameters
{
public string cap {get; set;}
public string Capability
{
get { return cap; }
}
public string Id { get; set; }
}
これで、コントローラーで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
プロパティが含まれます。しかし、なぜ誰かがクエリパラメータでそれを行う必要があるのかわかりません。
私は同じ問題の堅牢な解決策に数時間を費やしましたが、ワンライナーでうまくいく場合は次のようになります。
myModel.Capability = HttpContext.Current.Request["cap"];