2015-07-26 3 views
9

В настоящее время для каждого GET мне нужно вручную создать объект запроса из параметров маршрута.Маршрутизация атрибутов WebApi - привязать параметр маршрута к объекту для GET

Возможно ли связать непосредственно с объектом запроса?

Таким образом, вместо того, чтобы:

[Route("{id:int}")] 
public Book Get(int id) { 

    var query = new GetBookByIdQuery { 
     Id = id 
    }; 

    // execute query and return result 
} 

Я мог бы сделать это:

[Route("{id:int}")] 
public Book Get(GetBookByIdQuery query) { 
    // execute query and return result 
} 

Где GetBookByIdQuery выглядит следующим образом:

public class GetBookByIdQuery { 
    public int Id { get; set;} 
} 
+0

Я не могу понять, почему вы хотите потратить свое время на это. В чем проблема использования идентификатора вместо GetBookByIdQuery? Можете ли вы сказать немного больше о цели или использовании этого предложения? –

+3

Да, почему это пустая трата времени? Для сообщений в WebApi вы привязываетесь непосредственно к строго типизированной модели, а не привязываетесь к каждому отдельному полю, а затем сами заполняете сильно типизированную модель. Почему GET должен быть другим. Прямо сейчас я должен взять каждый связанный параметр и создать свой строго типизированный объект запроса, а не просто привязать его к этому объекту. – kimsagro

+0

Ваш подход нарушит стандарт REST. Вы отвечаете на запрошенный идентификатор ресурса, а не на модель. REST четко определен как GET, PUT, POST, PATCH и DELETE, а ASP.NET Web API 2 - для создания приложений REST. Возможно, вы новатор. Тогда вам нужно оправдать ваш подход. Я сделал аналогичные вещи в ASP.NET MVC с привязкой к модели. Вы можете найти его для Web API здесь http: //www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api Мне сильно не нравится ваше предложение GET, но я надеюсь, что это может вам помочь –

ответ

6

читать сложный тип из URI, [FromUri] можно использовать

[Route("{id:int}")] 
    public Book Get([FromUri] GetBookByIdQuery query) { 

     // execute query and return result 
    } 

если вы запрашиваете API/значения/2, то идентификатор свойство объекта запроса будет равно 2;

+0

, почему это отрицательно? – MstfAsan

+0

Это работает только для меня, если в строке запроса есть значения для сложного типа. Затем он примет идентификатор маршрута и значения строки запроса. –

1

Вы можете использовать класс в качестве параметра, но поскольку id больше не является параметром в определении метода, он не может быть включен в Маршрут.

public class LibraryController : ApiController 
{ 
    [HttpGet] 
    public Book Get(GetBookByIdQuery query) 
    { 
     // Process query... & return 
    } 
} 

Вы можете назвать это со ссылкой:

http://localhost:54556/api/Library?id=12 
+0

Я хочу использовать параметр маршрута, а не строку запроса – kimsagro

3

Ответ определить у вас есть HttpParameterBinding.

Вот пример, который я сделал.

Сначала я создал мой CustomParameterBinding

public class CustomParameterBinding : HttpParameterBinding 
{ 
    public CustomParameterBinding(HttpParameterDescriptor p) : base(p) { } 

    public override System.Threading.Tasks.Task ExecuteBindingAsync(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) 
    { 

     // Do your custom logic here 
     var id = int.Parse(actionContext.Request.RequestUri.Segments.Last()); 

     // Set transformed value 
     SetValue(actionContext, string.Format("This is formatted ID value:{0}", id)); 

     var tsc = new TaskCompletionSource<object>(); 
     tsc.SetResult(null); 
     return tsc.Task; 
    } 
} 

Следующим шагом является создание пользовательских атрибутов для украшения параметр:

public class CustomParameterBindingAttribute : ParameterBindingAttribute 
{ 
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) 
    { 
     return new CustomParameterBinding(parameter); 
    } 
} 

И, наконец, в настоящее время контроллер выглядит следующим образом:

public class ValuesController : ApiController 
{ 
    // GET api/values/5 
    [Route("api/values/{id}")] 
    public string Get([CustomParameterBinding] string id) 
    { 
     return id; 
    }  
} 

Так что теперь, когда я звоню http://localhost:xxxx/api/values/5

я получаю: "Это отформатирован значение ID: 5"