2013-09-08 2 views
2

У меня есть система проверки, настроенная для автоматической проверки параметров методов действия Web Api (включая методы действий OData). Однако это не работает для запросов PATCH, которые хранят измененные свойства в типе Delta<Entity>.ASP.NET Web Api OData: как проверить Delta <Entity>?

Я сделал некоторые копать вокруг и, как вы можете see in the ASP.NET source code из Delta, он имеет атрибут NonValidatingParameterBinding, что означает, что Delta «s не подвергаются проверке.

Теперь очевидным решением было бы применить дельта, а затем выполнить ручную проверку полученного объекта.

Но есть ли другие решения, которые не требуют применения патча? В идеале это должно произойти автоматически до того, как будет вызван метод действия ...

Спасибо.

ответ

3

Было явным конструктивным решением не утверждать Delta<Entity>. Причина в том, что Delta<Entity> является лишь частичной сущностью и по определению может быть недействительной. Как вы уже догадались, правильный подход заключается в проверке объекта после того, как поверх него наложено Delta<TEntity>.

Пример кода,

public void Patch(Delta<Customer> delta) 
{ 
    Customer c = new Customer(); 
    delta.Patch(c); 

    Validate(c, typeof(Customer)); 
} 

private void Validate(object model, Type type) 
{ 
    var validator = Configuration.Services.GetBodyModelValidator(); 
    var metadataProvider = Configuration.Services.GetModelMetadataProvider(); 

    HttpActionContext actionContext = new HttpActionContext(ControllerContext, Request.GetActionDescriptor()); 

    if (!validator.Validate(model, type, metadataProvider, actionContext, String.Empty)) 
    { 
     throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState)); 
    } 
} 

Полный образец here.

+0

Ну, это интересное дизайнерское решение, учитывая, что существуют валидаторы для отдельных свойств. Я создал фильтр, который проверяет одно измененное свойство Delta за раз, и он отлично работает ... что в этом плохого? Логика проверки здесь: http://pastebin.com/npSMxg9y; Атрибут фильтра здесь: http://pastebin.com/ARnstAJD –

+0

Ваш FilterAttribute полагается на предположение, что фреймворк работает с проверкой на Delta . Это предположение неверно. 'Delta ' явно отклоняется от проверки. Таким образом, не было бы ошибок проверки в «ModelState» и «ModelState.IsValid» было бы правдой, даже если модель недействительна. –

+0

Вот почему атрибут вызывает 'searchForAndValidateDelta', который ищет параметр Delta', переданный в действие, и проверяет каждое измененное значение свойства отдельно. И это работает великолепно, кстати :) Мой вопрос в том, есть ли какие-то больные побочные эффекты, о которых я должен знать. –

1

Мы тоже достигли этой проблемы. Однако мы используем пользовательскую версию Delta<T> (в значительной степени основанной на OData).

Основная проблема (кроме [NonValidatingParameterBinding]) заключается в том, что объект скрыт (за delta.GetEntity()) и, следовательно, не будет проверен. Также мы хотим только проверить измененные свойства.

Мы решили эту проблему путем добавления интерфейса IValidateObject в наш класс пользовательских Delta, делая подпись следующим образом:

[NonValidatingParameterBinding] 
public class Delta<TEntityType> : DynamicObject, IDelta, IValidatableObject 
    where TEntityType : class 

Это, вероятно, может также быть сделано в классе наследуемых от OData-х Delta<T>, но это не то, мы попробовали.

Реализация интерфейса выглядит следующим образом:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     var entity = this.GetEntity(); 

     var innerValidationContext = new ValidationContext(entity); 

     List<ValidationResult> validationResults = new List<ValidationResult>(); 

     foreach (var propertyName in this.GetChangedPropertyNames()) 
     { 
      innerValidationContext.MemberName = propertyName; 
      Validator.TryValidateProperty(EntityType.GetProperty(propertyName).GetValue(entity), innerValidationContext, validationResults); 
     } 

     return validationResults; 
    } 

Надеется, что это помогает! /Victor

Смежные вопросы