2012-08-10 14 views
5

Chciałem stworzyć globalny atrybut valdiation dla mojego Web API. Tak I po tutorial a zakończył się z następującym atrybut:ASP.NET MVC 4 RC Web API Błąd ModelState dla opcjonalnych parametrów adresu URL, które są zerowalne

public class ValidationActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if (actionContext.ModelState.IsValid) 
     { 
      return; 
     } 

     var errors = new List<KeyValuePair<string, string>>(); 
     foreach (var key in actionContext.ModelState.Keys.Where(key => 
      actionContext.ModelState[key].Errors.Any())) 
     { 
      errors.AddRange(actionContext.ModelState[key].Errors 
        .Select(er => new KeyValuePair<string, string>(key, er.ErrorMessage))); 
     } 

     actionContext.Response = 
      actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors); 
    } 
} 

Potem dodaje go do globalnych fitlers w Global.asax:

configuration.Filters.Add(new ValidationActionFilter());

Działa świetnie z większością moich działań ale nie zgodnie z oczekiwaniami w przypadku działań, które mają opcjonalne i zerowe parametry żądania.

Na przykład:

stworzyłem trasę:

i działanie w moim ProductsController:

public HttpResponseMessage GetAllProducts(int? skip, int? take) 
{ 
    var products = this._productService.GetProducts(skip, take, MaxTake); 

    return this.Request.CreateResponse(HttpStatusCode.OK, this._backwardMapper.Map(products)); 
} 

Teraz, kiedy żądania URL: http://locahost/api/products otrzymuję odpowiedź z kodem statusu 403 i następującą treścią:

[ 
{ 
    "Key": "skip.Nullable`1", 
    "Value": "A value is required but was not present in the request." 
}, 
{ 
    "Key": "take.Nullable`1", 
    "Value": "A value is required but was not present in the request." 
} 
] 

Wierzę, że to nie powinno być widoczne jako błąd sprawdzania poprawności, ponieważ parametry te są opcjonalne i zerowalne.

Czy ktoś napotkał ten problem i znalazł rozwiązanie?

Odpowiedz

2

Wydaje Ci zawiedli kodu pomiędzy Web API i MVC, należy użyć RouteParameter z Web API zamiast UrlParameter z MVC

routes.MapHttpRoute(
    name: "Optional parameters route", 
    routeTemplate: "api/{controller}", 
    defaults: new { skip = RouteParameter.Optional, take = RouteParameter.Optional } 
    ); 

ALE:

domyślne parametry twojego route pomiń i weź nie odgrywaj żadnej roli dla mechanizmu trasy, ponieważ używasz ich tylko w ciągu zapytania, a nie w szablonie trasy. Więc trasa najbardziej naprawcze powinny być:

routes.MapHttpRoute(
    name: "Optional parameters route", 
    routeTemplate: "api/{controller}" 
    ); 
+1

Dobry punkt, ale nadal nie rozwiązuje problemu tutaj. Oba parametry są "wymagane" i zawierają błędy w słowniku ModelState, mimo że są zerowe. Czy znasz sposób oznaczania parametru działania jako nie wymagany? –

+0

Czy wypróbowałeś to rozwiązanie w swoim kodzie? –

+0

Jeśli chodzi o twoje pytanie, użyj opcjonalnych parametrów. –

4

Można też uniknąć/walidacji modelu eliminują dla prymitywnych typów w żądaniu GET ..

public class ModelValidationFilter : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(HttpActionContext actionContext) 
     { 
      if (!actionContext.ModelState.IsValid && actionContext.Request.Method != HttpMethod.Get) 
      { ... 
+0

Czy możesz rozwinąć? –

Powiązane problemy