2016-07-19 2 views
2

У меня есть приложение ASP.NET WebAPI со следующим контроллером и маршруту:C# ASP.NET WebAPI шаблон маршрута не работает с Ури параметрами

WebApiConfig.cs

var constraintResolver = new DefaultInlineConstraintResolver(); 
constraintResolver.ConstraintMap.Add("validDate", typeof(DateConstraint)); 

Controller.cs

[HttpGet] 
[Route("deleted/{from:validDate?}/{to:validDate?}", Name = "GetDeletedData")] 
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(IEnumerable<SimpleClass>), Description = "response")] 
public async Task<HttpResponseMessage> Get(
    [FromUri]string from = "", 
    [FromUri]string to = "" 
    ) 
{ 

} 

Constraint

public class DateConstraint : IHttpRouteConstraint 
{ 
    public bool Match(
     HttpRequestMessage request, 
     IHttpRoute route, 
     string parameterName, 
     IDictionary<string, object> values, 
     HttpRouteDirection routeDirection 
     ) 
    { 
     object value; 

     if (!values.TryGetValue(parameterName, out value)) 
      return false; 

     var attribute = new DateAttribute(); 

     return attribute.IsValid(value); 
    } 
} 

Вышеуказанный маршрут ударил, хотя я передаю следующий URL-адрес, т.е. я не перехожу от и к параметрам, но контроллер попал и ничего не происходит.

http://localhost:65190/products/deleted?adfear=2016-07-01 03:30:05&adfaewr=2016-07-01 03:30:05 

Как убедиться, что маршрут попал только при правильных параметрах или сбросе 404 не найдена ошибка?

ответ

3

Зачем изобретать колесо.

Attribute Routing in ASP.NET Web API 2:Route Constraints

уже существует datetime ограничения.

Также вы можете сделать только последнюю дату, чтобы, если она предоставлена ​​с даты, она будет фильтроваться с использованием даты от даты до текущей даты.

[HttpGet] 
[Route("deleted/{from:datetime}/{to:datetime?}", Name = "GetDeletedData")] 
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(IEnumerable<SimpleClass>), Description = "response")] 
public async Task<HttpResponseMessage> Get(DateTime from, DateTime? to = null) 
{ 
    //.... 
} 

на основе ваших комментариев вы можете сделать что-то вроде этого

//GET products/deleted 
[HttpGet] 
[Route("deleted")] 
public async Task<HttpResponseMessage> Get() { 
    //... 
} 

//GET products/deleted/2016-01-01 
//GET products/deleted/2016-01-01/2016-03-31 
[HttpGet] 
[Route("deleted/{from:datetime}/{to:datetime?}", Name = "GetDeletedData")] 
public async Task<HttpResponseMessage> Get(DateTime from, DateTime? to = null) { 
    //... 
} 

теперь это должен обрабатывать три случая

//GET products/deleted 
//GET products/deleted/{from} 
//GET products/deleted/{from}/{to} 

Обновление

Если режим факультативного

//GET products/deleted - including query string will hit this 
//GET products/deleted?adfear=2016-07-01 03:30:05&adfaewr=2016-07-01 03:30:05 
//GET products/deleted/2016-01-01 
//GET products/deleted/2016-01-01/2016-03-31 
[HttpGet] 
[Route("deleted/{from:datetime?}/{to:datetime?}", Name = "GetDeletedData")] 
public async Task<HttpResponseMessage> Get(DateTime? from = null, DateTime? to = null) { 
    //... 
} 

Update2

на основе разговора

оба параметра вы можете создать модель фильтра

public class DateRangeFilter { 
    public DateTime? from { get; set; } 
    public DateTime? to { get; set; } 
} 

и вы можете использовать это в своем действии ,

// GET products/deleted 
// GET products/deleted?from=2016-01-01&to=2016-03-31 
[HttpGet] 
[Route("deleted", Name = "GetDeletedData")] 
public async Task<HttpResponseMessage> Get([FromUri]DateRangeFilter filter) { 
    //... 
} 

Также не забудьте проверить модель через фильтр или внутри действия.

+0

Мое требование - поля могут быть необязательными. –

+0

Если они оба являются необязательными, то вызовы по умолчанию '/ deleted' будут конфликтовать с этим действием. Это потому, что 'Get()' и 'Get (DateTime? From = null, DateTime? To = null)' считаются одинаковыми, и структура не будет знать, какой из них использовать – Nkosi

+0

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

2

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

[HttpGet] 
[Route("deleted/{from:validDate}/{to:validDate}", Name = "GetDeletedData")] 
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(IEnumerable<SimpleClass>), Description = "response")] 
public async Task<HttpResponseMessage> Get(
    [FromUri]string from = "", 
    [FromUri]string to = "" 
    ) 
{ 

} 
+0

Но мое требование состоит в том, что поля могут быть необязательными. –

1

Вы должны опустить знак вопроса на ограничения и значения по умолчанию для ваших параметров:

[HttpGet] 
[Route("deleted/{from:validDate}/{to:validDate}", Name = "GetDeletedData")] 
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(IEnumerable<SimpleClass>), Description = "response")] 
public async Task<HttpResponseMessage> Get(
    [FromUri]string from, 
    [FromUri]string to 
    ) 
{ 

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