У меня есть контроллер

   [HttpGet]
    [RoutePrefix("api/products/{productId}")] 
    public HttpResponseMessage Products(int productId,TypeEnum ptype=TypeEnum.Clothes)
{
    if(!Enum.IsDefined(typeOf(TypeEnum),ptype))
      //throw bad request exception
    else
      //continue processing
}

Myenum объявлен как

public TypeEnum
{
  Clothes,
  Toys,
  Electronics
}

В настоящее время, если передается какое-то значение мусора, оно преобразуется в значение по умолчанию. Что я хочу сделать, так это если я назову контроллер как api / products / 1, тогда типу ptype следует присвоить значение по умолчанию, то есть одежду. Если я вызываю контроллер как api / products / 1? PType = somegarbagevalue, тогда контроллер должен генерировать исключение неверного запроса. Как я могу этого добиться?

11
user3832953 13 Июл 2014 в 11:10

3 ответа

Лучший ответ

Вы должны иметь дело с string и использовать TryParse() для преобразования строки в значение Enum.

public HttpResponseMessage Products(int productId,string ptype="Clothes")
{
    TypeEnum category = TypeEnum.Clothes;
    if(!Enum.TryParse(ptype, true, out category))
      //throw bad request exception if you want. but it is fine to pass-through as default Cloathes value.
    else
      //continue processing
}

Это может показаться наивным, но преимущество этого подхода состоит в том, чтобы разрешить параметр ptype для любой строки и выполнять процесс без исключения, когда ptype не может связать значение.

7
Youngjae 12 Сен 2014 в 20:00

Этот тип проверки должен выполняться в конвейере, а не в контроллере.

    public abstract class ETagMatchAttribute : ParameterBindingAttribute
{
    private ETagMatch _match;

    public ETagMatchAttribute(ETagMatch match)
    {
        _match = match;
    }

    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
    {
        if (parameter.ParameterType == typeof(ETag))
        {
            return new ETagParameterBinding(parameter, _match);
        }
        return parameter.BindAsError("Wrong parameter type");
    }
}

Что-то вроде этого. см. ссылку ссылка MSDN для подробного объяснения

0
Taran 2 Май 2019 в 22:08

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

Это проблема привязки параметров, и ее не следует решать на уровне контроллера, о ней следует позаботиться в конвейере. Один из способов сделать это - создать собственный фильтр и добавить его в конфигурацию.

public class ModelStateValidationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = <your standardised error response>
        }
    }
}

И в вашем global.asax.cs

...
GlobalConfiguration.Configure(WebApiConfig.Register);
...

public class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...
        config.Filters.Add(new ModelStateValidationAttribute());
        ...
    }
}

Если у вас возникли проблемы с состоянием модели, это тип ModelStateDictionary, и вы просто перебираете его, а затем свойство Errors содержит все проблемы с привязкой модели. например

modelState = actionContext.ModelState;
modelState.ForEach(x =>
        {
            var state = x.Value;
            if (state.Errors.Any())
            {
                foreach (var error in state.Errors)
                {
                    <work your magic>
                }
            }
        });
14
HeroicNonsense 19 Мар 2015 в 05:39
1
Я не совсем понимаю это решение. Где ваш код использует/обрабатывает TypeEnum из вопроса? Я задал связанный вопрос, который также связан с вашим.
 – 
O. R. Mapper
24 Янв 2018 в 17:26