Search code examples
openrasta

OpenRasta: Uri seems to be irrelevant for handler selection


When registering two handlers for the same type, but with different URIs, the handler selection algorithm doesn't seem to check the uri when it determines which handler to use.

If you run the program below, you'll notice that only HandlerOne will be invoked (twice). It does not matter if I call for "/one" or "/two", the latter supposed to be handled by HandlerTwo.

Am I doing something wrong or is this something to be fixed in OpenRasta? (I'm using 2.0.3.0 btw)

class Program
{
    static void Main(string[] args)
    {
        using (InMemoryHost host = new InMemoryHost(new Configuration()))
        {
            host.ProcessRequest(new InMemoryRequest
            {
                HttpMethod = "GET",
                Uri = new Uri("http://x/one")
            });
            host.ProcessRequest(new InMemoryRequest
            {
                HttpMethod = "GET",
                Uri = new Uri("http://x/two")
            });
        }
    }
}
class Configuration : IConfigurationSource
{
    public void Configure()
    {
        using (OpenRastaConfiguration.Manual)
        {
            ResourceSpace.Has.ResourcesOfType(typeof(object))
                .AtUri("/one").HandledBy(typeof(HandlerOne));
            ResourceSpace.Has.ResourcesOfType(typeof(object))
                .AtUri("/two").HandledBy(typeof(HandlerTwo));
        }
    }
}
class HandlerOne
{
    public object Get() { return "returned from HandlerOne.Get"; }
}
class HandlerTwo
{
    public object Get() { return "returned from HandlerTwo.Get"; }
}

Update I have a feeling that I could accomplish what I want similar using UriNameHandlerMethodSelector as described on http://trac.caffeine-it.com/openrasta/wiki/Doc/Handlers/MethodSelection, but then I'd have to annotate each handler methods and also do AtUri().Named(), which looks like boilerplate to me and I'd like to avoid that. Isn't AtUri(X).HandledBy(Y) making the connection between X and Y clear?


Solution

  • Eugene,

    You should never have multiple registrations like that on the same resource type, and you probably never need to have ResourcesOfType<object> ever associated with URIs, that'll completely screw with the resolution algorithms used in OpenRasta.

    If you're mapping two different things, create two resource classes. Handlers and URIs are only associate by resource class, and if you fail at designing your resources OpenRasta will not be able to match the two, and this is by design.

    If you want to persist down that route, and I really don't think you should, then you can register various URIs to have a name, and hint on each of your methods that the name ought to be handled using HttpOperation(ForUriName=blah). That piece of functionality is only there for those very, very rare scenarios where you do need to opt-out of the automatic method resolution.

    Finally, as OpenRasta is a compsable framework, you shouldnt have to go and hack around existing classes, you ought to plug yourself into the framework to ensure you override the components you don't want and replace them by things you code yourself. In this case, you could simply write a contributor that replaces the handler selection with your own moel if you don't like the defaults and want an MVC-style selection system. Alternatively, if you want certain methods to be selected rather than others, you can remove the existing operation selectors and replace them (or complement them with) your own. That way you will rely on published APIs to extend OpenRasta and your code won't be broken in the future. I can't give that guarantee if you forked and hacked existing code.