A set of add ons and extensions for ASP.NET Web API.
install-package climax.web.http
git clone https://github.com/climax-media/climax-web-http.git
cd climax-web-http
build.cmd
ThreadCultureMessageHandler
- ensures culture is set (Thread.CurrentThread.CurrentCulture
andThread.CurrentThread.CurrentUICulture
. Parsed fromAccept-Language
header orAcceptLanguage
querystring
config.MessageHandlers.Add(new ThreadCultureMessageHandler(setThreadCulture: true, setThreadUiCulture: true, fallBackCulture: new CultureInfo("en-US")));
HeadMessageHandler
- adds support for HEAD HTTP verb
config.MessageHandlers.Add(new HeadMessageHandler());
NonControllerHttpControllerTypeResolver
- allows you to use API controllers without "Controller" suffix
config.Services.Replace(typeof(IHttpControllerTypeResolver), new NonControllerHttpControllerTypeResolver());
You can now do i.e.:
public class CustomerResource : ApiController
{
[Route("customer")]
public string Get()
{
return "customer";
}
}
And reach this resource via /customer
route or centrally - /api/customerresource
.
Note - this means that the Controller
is no longer stripped. So if you have FooController
, the centralized routing mechanism will see it as /api/foocontroller
.
PerControllerConfigActivator
- supports HttpConfiguration per controller that can be set up at runtime. Normally Web API only allows static per controller configuration
config.AddControllerConfigurationMap(new Dictionary<Type, Action<HttpControllerSettings>>
{
{
typeof (ValuesController), settings =>
{
settings.Formatters.Clear();
settings.Formatters.Add(new JsonMediaTypeFormatter());
}
}
});
config.Services.Replace(typeof(IHttpControllerActivator), new PerControllerConfigActivator());
SmartHttpActionInvoker
- saves the information of the action return type underRuntimeReturnType
key of request properties. Web API normally only exposes the type information from the action descriptor.
config.Services.Replace(typeof(IHttpActionInvoker), new SmartHttpActionInvoker());
// then anywhere:
config.Get<Type>("RuntimeReturnType");
JsonContentNegotiator
- switch off content negotiation in your API completely - support JSON only, in the most efficient way
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
RouteDataValuesOnlyAttribute
- disables binding of simple parameters from querystring (only from route data). Applied at controller level.
[RouteDataValuesOnly]
public class TestController : ApiController
{
//foo will only be bound from route data not from querystring
public string Get(string foo)
{
return foo;
}
}
InjectParameterBinding
- allows you to inject your dependencies (services and such, that are resolved from Web API dependency resolver) directly into actions, rather than through constructor
Instead of:
public class MyController : ApiController
{
private readonly IFooService _fooService;
private readonly IBarService _barService;
public MyController(IFooService fooService, IBarService barService)
{
_fooService = fooService;
_barService = barService;
}
[Route("foo")]
public void PostFoo(FooModel foomodel)
{
_fooService.Process(foomodel);
}
[Route("bar")]
public void PostBar(BarModel barmodel)
{
_barService.Process(barmodel);
}
}
You can do:
public class MyController : ApiController
{
[Route("foo")]
public void PostFoo(FooModel foomodel, [Inject]IFooService fooService)
{
fooService.Process(foomodel);
}
[Route("bar")]
public void PostBar(BarModel barmodel, [Inject]IBarService barService)
{
barService.Process(barmodel);
}
}
You don't have to do anything else - as long as Web API dependency injection is wired up globally (which it should - for constructor injection), this will just work.
Support versioning based on attribute routing - using URI versioning, header versioning or content type versioning
You can set up two versions of same resource:
public class NewValuesController : ApiController
{
[VersionedRoute("values", Version = 2)]
public string Get()
{
return "i'm new";
}
}
public class OldValuesController : ApiController
{
[VersionedRoute("values", Version = 1)]
public string Get()
{
return "i'm old";
}
}
For URI versioning, simply use the route template i.e.:
[VersionedRoute("v2/values", Version = 2)]
If you want header versioning, you need to set up the versioning first:
config.ConfigureVersioning(versioningHeaderName: "version", vesioningMediaTypes: null);
The following HTTP request gives you the new resource:
GET /values
version: 2
If you want media type versioning you also need to set it up:
config.ConfigureVersioning(versioningHeaderName: null, vesioningMediaTypes: new [] { "application/vnd.climax"});
The following HTTP request gives you the new resource (version delimited by -v
and +
):
GET /values
Accept: application/vnd.climax-v2+json
You can also implement your own IVersionParser
and plug it in (or inherit the base VersionParser
) if you want full control over header parsing.
config.ConfigureVersioning(new MyVersionParser());
FileHttpActionResult
- return a file asStreamContent
FileWithDispositionHttpActionResult
- return a file asByteArrayContent
, with a relevantContent-Disposition
headerPlainTextResult
- return plain text result
A bunch of extension methods for HttpRequestMessage
and HttpConfiguration
.
StringArrayModelBinder
- bind a collection in an action from a comma separated querystring valueCheckModelStateAttribute
- validate model state through action filter