2016-11-03 4 views
2

Я использую веб-апи фильтр для проверки всех входящих моделей просмотра и возврата состояния ошибки просмотра, если это нуль:Необязательный атрибут в ASP.NET Web API маршрутизации

public class ValidateViewModelAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if(actionContext.ActionArguments != null) 
     { 
      foreach (var argument in actionContext.ActionArguments) 
      { 
       if (argument.Value != null) 
        continue; 

       var argumentBinding = actionContext.ActionDescriptor?.ActionBinding.ParameterBindings 
        .FirstOrDefault(pb => pb.Descriptor.ParameterName == argument.Key); 

       if(argumentBinding?.Descriptor?.IsOptional ?? true) 
        continue; 

       actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, string.Format("Arguments value for {0} cannot be null", argument.Key)); 
       return; 
      } 
     } 

     if (actionContext.ModelState.IsValid == false) 
     { 
      actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState); 
     } 
    } 
} 

У меня есть веб-интерфейс API, работающих в производстве и в настоящее время У меня появился новый запрос добавить один необязательный параметр к одному действию. Дополнительно .... для сохранения совместимости API

[Route("applyorder/{orderId}")] 
    [HttpPost] 
    public async Task<IHttpActionResult> ApplyOrder(int orderId, [FromBody] ApplyOrderViewModel input = null) 

и если я не указываю вход = null это не считается необязательных параметров и не мог пройти мимо моей проверки. С = null я получаю следующее сообщение об ошибке:

"Message": "An error has occurred.", "ExceptionMessage": "Optional parameter 'input' is not supported by 'FormatterParameterBinding'.",
"ExceptionType": "System.InvalidOperationException", "StackTrace": " at System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync(

Как я могу сохранить свою глобальную проверку ViewModel на месте и по-прежнему отмечают этот параметр только метод будет необязательным.

  • пс: Я не могу использовать синтаксис маршрута с ? знаком, потому что это [FromBody]
  • PSS: Я бы не хотел вводить v2 API, потому что это не v2 апи, я добавляю новый необязательный параметр
  • psss: Мне нужен какой-то атрибут , чтобы обновить дескриптор привязки и указать, что мой параметр необязательный, то он пройдет мою проверку.

ответ

2

Поскольку это ваша собственная проверка, что она не может пройти без = null вы можете добавить пользовательский атрибут [OptionalParameter] и проверять его наличие, например, если вы должны сделать некоторое кэширование по типу, чтобы избежать чрезмерного использования Reflection.

Второй вариант состоит в том, чтобы иметь базовый класс для всех ваших дополнительных параметров, как показано ниже, и просто проверить с помощью оператора is.

public abstract class OptionalParameter 
{ 
} 

Третий вариант - сделать то же самое с интерфейсом.

Хотя атрибут является самым чистым, на мой взгляд, это немного сложнее реализовать.

+0

атрибут с аргументом метода? Итак, это будет выглядеть как [[Необязательно] [FromBody] ApplyOrderViewModel input'? Я думал о настройке '[FromBody]', чтобы добавить возможность определить его как необязательный, но этот класс запечатан, и я не могу много чего с этим поделать. Основная идея состоит в том, чтобы сохранить валидацию одинаковой, но подстроить определение моего метода, чтобы заставить привязку параметров понимать, что это необязательный параметр 'argumentBinding? .Descriptor? .IsOptional' –

+1

Да, дополнительный атрибут, как вы описали' [Optional] '. Вам нужно будет использовать отражение, чтобы проверить, существует ли атрибут. Хотя кажется, что вы уже используете отражение там, поэтому вам просто нужно добавить простую проверку атрибута. –

+0

Я предполагаю, что это предложение лучше всего реализовать и использовать. Ясное и элегантное :) спасибо –

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