-
Notifications
You must be signed in to change notification settings - Fork 1
Handler Method Selection
The methods on a handler get selected through multiple stage in the pipeline. It’s important to note that every method will get processed until only one is left.
The first step of the selection process uses a list of filters to narrow down the number of methods being matched.
By default, two filters are automatically registered.
HttpMethodHandlerMethodSelector
::
- All methods starting with the HTTP method name. For example, for a GET HTTP method, both a
Get()
and aGetCustomer()
method will be selected. - All methods containing the
HttpOperationAttribute
with a matching HTTP method name.
UriNameHandlerMethodSelector
::
- If the request URI is not associated with a name (through the
AtUri().Named()
method), all the methods will be selected. - If there is a URI name,
- If there are methods with an
HttpOperationAttribute
with aForUriName
property matching the URI name, those methods will be selected - Otherwise, all the methods will be selected
- If there are methods with an
In the following step, the pipeline will take the URI parameters defined in the URI templates, and will try to assign the properties to the parameters of the method. An error is thrown if the parameterized portion of the URI ({page}
) cannot be converted to the method parameter type.
In the following example, the value of the {page}
URI template parameter will be assigned to the page
parameter of the Get
method.
The import bit to remember is that the parameterized sections of the URI should match a parameter name
in a public
method that starts with Get
.
ResourceSpace.Has.ResourcesOfType<Page>().AtUri("/pages/{page}")
...
public OperationResult Get(int page)
Another example might be:
ResourceSpace.Has.ResourcesOfType<List<Page>>().AtUri("/pages?pagesNamedLike={pagesNamedLike}")
...
public OperationResult GetByPagesNamedLike(string pagesNamedLike)
Here, the method name
GetByPagesNamedLike
is not important, but the parameter pagesNamedLike
is.
If an HTTP POST method contains form data in the body of the request, it can be matched to a Post
method which defines an object parameter whose public property names match the form element names.
The following example first defines a simple HTML form, a CustomerPost
class which matches some of those form elements, and a handler with a Post
method using the CustomerPost
class.
<form method="post" action="/customer">
First Name: <input type="text" name="firstname" ><br>
Last Name: <input type="text" name="lastname" ><br>
<input type="submit">
</form>
...
ResourceSpace.Has.ResourcesOfType<CustomerPost>().AtUri("/customer").HandledBy<CustomerHandler>();
...
public class CustomerPost
{
public string firstname { get; set; }
public string lastname { get; set; }
public int balance { get; set; } // will not affect selection
}
...
public class CustomerHandler
{
public object Post(CustomerPost formdata)
{
return new CustomerResource(formdata.firstname, formdata.lastname);
}
}
The following JQuery method sends an HTTP DELETE request to the server. OpenRasta will match it to a ‘Delete’ method with a single ID parameter.
function onDelete(theId) {
$.ajax({
url: 'Customer',
type: 'DELETE',
data: ({ id: theId }),
success: function () { alert('DELETE completed'); }
});
}
...
ResourceSpace.Has.ResourcesOfType<Customer>().AtUri("/customer").HandledBy<CustomerHandler>();
...
public class CustomerPost
{
public string firstname { get; set; }
public string lastname { get; set; }
public int balance { get; set; } // will not affect selection
public int ID;
}
...
public class CustomerHandler
{
public void Delete( int customerID)
{
}
}
The following form will be able to post to the given handler and read a file.
<form action="/documentlist"
enctype="multipart/form-data" method="post">
<p>
Type some text (if you like):<br />
<input type="text" name="textline" size="30" />
</p>
<p>
Please specify a file, or a set of files:<br />
<input type="file" name="document" size="40" />
</p>
<div>
<input type="submit" value="Send" />
</div>
</form>
...
public OperationResult Post( IEnumerable<IMultipartHttpEntity> entities)
{
foreach (var entity in entities)
{
if (entity.Stream != null && entity.ContentType != null)
{
var memoryStream = new MemoryStream();
entity.Stream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
}
}
return new OperationResult.Created();
}
Note that you must read the streams the first time entities is iterated.