Изменение имени параметра. Привязка модели Web Api.
Я использую привязку модели 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
}
Ответы
Ответ 1
Вы можете использовать свойство Name атрибута привязки FromUri для использования параметров строки запроса с разными именами в аргументах метода.
Если вы передаете простые параметры, а не свой тип QueryParameters
, вы можете привязать значения следующим образом:
/api/values/5?cap=somecap&id=1
public IHttpActionResult GetValue([FromUri(Name = "cap")] string capabilities, int id)
{
}
Ответ 2
Web API использует немного другой механизм привязки к модели, чем ASP.NET MVC. Он использует formatters для данных, переданных в теле и вложениях модели для данных, передаваемых в строке запроса (как в вашем случае). Форматы учитывают дополнительные атрибуты метаданных, в то время как привязки моделей не работают.
Итак, если вы передали свою модель в теле сообщения, а не в строке запроса, вы могли бы аннотировать ваши данные следующим образом, и это сработало бы:
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)
Ответ 3
Я провел несколько часов, работая над надежным решением одной и той же проблемы, когда однострочный трюк будет очень трюк:
myModel.Capability = HttpContext.Current.Request["cap"];
Ответ 4
Я просто столкнулся с этим и использовал getter в моем классе параметров, чтобы вернуть свойство bound.
Итак, в вашем примере:
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 only a getter
}
Конечно, если вы используете отражение объекта param
или сериализуете его, будет включено свойство cap
. Не уверен, почему кому-то нужно будет это делать с параметрами запроса.