Request Contracts
HTTP request contracts define the shape of your API calls using interfaces and attributes. Every HTTP contract implements IHttpRequest<TResult> and is decorated with attributes that describe the HTTP verb, route, parameters, and body.
IHttpRequest<TResult>
Section titled “IHttpRequest<TResult>”All HTTP contracts must implement IHttpRequest<TResult> where TResult is the deserialized response type.
using Shiny.Mediator.Http;
[Http(HttpVerb.Get, "/api/users/{Id}")]public class GetUserRequest : IHttpRequest<UserResponse>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }}The [Http] Attribute
Section titled “The [Http] Attribute”The [Http] attribute defines the HTTP verb and route template for the request.
[Http(HttpVerb.Get, "/api/resource")][Http(HttpVerb.Post, "/api/resource")][Http(HttpVerb.Put, "/api/resource/{Id}")][Http(HttpVerb.Patch, "/api/resource/{Id}")][Http(HttpVerb.Delete, "/api/resource/{Id}")]HTTP Verb Examples
Section titled “HTTP Verb Examples”GET - Retrieve data
[Http(HttpVerb.Get, "/api/products")]public class GetProductsRequest : IHttpRequest<List<Product>>{ [HttpParameter(HttpParameterType.Query)] public string Category { get; set; }
[HttpParameter(HttpParameterType.Query)] public int Page { get; set; } = 1;}POST - Create a resource
[Http(HttpVerb.Post, "/api/products")]public class CreateProductRequest : IHttpRequest<Product>{ [HttpBody] public CreateProductDto Body { get; set; }}PUT - Replace a resource
[Http(HttpVerb.Put, "/api/products/{Id}")]public class UpdateProductRequest : IHttpRequest<Product>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }
[HttpBody] public UpdateProductDto Body { get; set; }}PATCH - Partially update a resource
[Http(HttpVerb.Patch, "/api/products/{Id}")]public class PatchProductRequest : IHttpRequest<Product>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }
[HttpBody] public PatchProductDto Body { get; set; }}DELETE - Remove a resource
[Http(HttpVerb.Delete, "/api/products/{Id}")]public class DeleteProductRequest : IHttpRequest<Product>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }}The [HttpParameter] Attribute
Section titled “The [HttpParameter] Attribute”The [HttpParameter] attribute maps a property to a specific part of the HTTP request. There are three parameter types:
Path Parameters
Section titled “Path Parameters”Path parameters are substituted into the route template. The property name must match the {placeholder} in the route.
[Http(HttpVerb.Get, "/api/users/{UserId}/orders/{OrderId}")]public class GetOrderRequest : IHttpRequest<OrderResponse>{ [HttpParameter(HttpParameterType.Path)] public string UserId { get; set; }
[HttpParameter(HttpParameterType.Path)] public string OrderId { get; set; }}Query Parameters
Section titled “Query Parameters”Query parameters are appended to the URL as query string values.
[Http(HttpVerb.Get, "/api/search")]public class SearchRequest : IHttpRequest<SearchResults>{ [HttpParameter(HttpParameterType.Query)] public string Term { get; set; }
[HttpParameter(HttpParameterType.Query)] public int PageSize { get; set; } = 25;
[HttpParameter(HttpParameterType.Query)] public string SortBy { get; set; }}
// Resulting URL: /api/search?Term=hello&PageSize=25&SortBy=nameHeader Parameters
Section titled “Header Parameters”Header parameters are added as HTTP request headers.
[Http(HttpVerb.Get, "/api/data")]public class GetDataRequest : IHttpRequest<DataResponse>{ [HttpParameter(HttpParameterType.Header)] public string ApiVersion { get; set; } = "2.0";
[HttpParameter(HttpParameterType.Header)] public string CorrelationId { get; set; }}The [HttpBody] Attribute
Section titled “The [HttpBody] Attribute”The [HttpBody] attribute marks a property to be serialized as the JSON request body.
[Http(HttpVerb.Post, "/api/orders")]public class CreateOrderRequest : IHttpRequest<OrderResponse>{ [HttpBody] public OrderDto Order { get; set; }}There can only be one [HttpBody] property per contract. The body is serialized to JSON.
Complete CRUD Example
Section titled “Complete CRUD Example”Here’s a full set of contracts for a typical CRUD API:
using Shiny.Mediator;using Shiny.Mediator.Http;
// List[Http(HttpVerb.Get, "/api/products")]public class ListProductsRequest : IHttpRequest<List<Product>>{ [HttpParameter(HttpParameterType.Query)] public string Category { get; set; }
[HttpParameter(HttpParameterType.Query)] public int Page { get; set; } = 1;
[HttpParameter(HttpParameterType.Query)] public int PageSize { get; set; } = 25;}
// Get by ID[Http(HttpVerb.Get, "/api/products/{Id}")]public class GetProductRequest : IHttpRequest<Product>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }}
// Create[Http(HttpVerb.Post, "/api/products")]public class CreateProductRequest : IHttpRequest<Product>{ [HttpBody] public CreateProductDto Body { get; set; }}
// Update[Http(HttpVerb.Put, "/api/products/{Id}")]public class UpdateProductRequest : IHttpRequest<Product>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }
[HttpBody] public UpdateProductDto Body { get; set; }}
// Delete[Http(HttpVerb.Delete, "/api/products/{Id}")]public class DeleteProductRequest : IHttpRequest<Product>{ [HttpParameter(HttpParameterType.Path)] public string Id { get; set; }}Usage:
IMediator mediator; // injected
// List productsvar products = await mediator.Request(new ListProductsRequest{ Category = "electronics", Page = 1});
// Get single productvar product = await mediator.Request(new GetProductRequest { Id = "123" });
// Create productvar created = await mediator.Request(new CreateProductRequest{ Body = new CreateProductDto { Name = "Widget", Price = 9.99m }});
// Update productvar updated = await mediator.Request(new UpdateProductRequest{ Id = "123", Body = new UpdateProductDto { Name = "Updated Widget", Price = 12.99m }});
// Delete productvar deleted = await mediator.Request(new DeleteProductRequest { Id = "123" });Combining All Parameter Types
Section titled “Combining All Parameter Types”A single contract can use path, query, header, and body parameters together:
[Http(HttpVerb.Post, "/api/v1/tenants/{TenantId}/items")]public class CreateItemRequest : IHttpRequest<ItemResponse>{ [HttpParameter(HttpParameterType.Path)] public string TenantId { get; set; }
[HttpParameter(HttpParameterType.Query)] public bool Validate { get; set; } = true;
[HttpParameter(HttpParameterType.Header)] public string CorrelationId { get; set; }
[HttpBody] public CreateItemDto Body { get; set; }}