-
Notifications
You must be signed in to change notification settings - Fork 66
Add your own interfaces
Simple.Web handlers implement interfaces, either to ask for information from the request, or to indicate that they will supply specific information to the response. For example, the IRequireAuthentication interface tells the framework that the user must be logged in, and adds a CurrentUser
property to the handler which the framework will set if the user is authenticated. If they're not, they'll be redirected to the login page.
This system is extensible, so that it is easy to add your own interfaces and the code to hook them up. The built-in behaviours are nearly all based on the same system, so your extensions are treated no differently to the core functionality. As an example, here is some code to get the raw query-string from the URI, if you needed that sort of thing:
[RequestBehavior(typeof(SetQueryString))]
public interface IQueryString
{
public IDictionary<string,string[]> QueryString { get; set; }
}
public static class SetQueryString
{
public static void Impl(IQueryString handler, IContext context)
{
handler.QueryString = context.Request.QueryString;
}
}
So, the RequestBehavior
attribute is applied to the interface to say it's part of the handler-setup phase of the request lifecycle, and you supply the type of the implementation class.
The implementation class should be public and static, with a public static method called Impl
, which takes an instance of the interface as its first parameter, and an IContext
as its second.
The Impl
method can return either void
or bool
; if its return type is bool
and the method returns false
, the request lifecycle is stopped at that point.
As well as RequestBehavior
, there are ResponseBehavior
and OutputBehavior
attributes. The way they are all called is as follows:
- RequestBehavior implementations;
- Handler's primary method (e.g. Get, Post, etc.)
- ResponseBehavior implementations;
- OutputBehavior implementations.
The only things that happen outside of this extensible pipeline are cookie handling (which don't use interfaces) and redirection (which happens before ResponseBehavior, if a Redirect-y status is returned).
To get a better idea of how this all works, you can check out the Behaviors namespace in the core code.
Try to use this extensible pipeline to maintain the separation between IContext
, IRequest
and IResponse
and the actual application code in your handlers. As soon as you introduce a dependency on any of those interfaces, you're into Mocking Hell, which is exactly what this whole system is trying to avoid.