visualeyes / halcyon

A HAL implementation for ASP.NET
MIT License
81 stars 30 forks source link

How to return URI templates in links? #68

Open alastairs opened 6 years ago

alastairs commented 6 years ago

The HAL specification seems to allow for URI templates in links, with parameters denoted in braces, e.g. "href": "/orders{?id}". How is this achieved in Halcyon? Using this syntax in a link URL causes Halcyon to attempt to substitute the parameter with a value from the model, and using double braces to escape the template causes an ArgumentException to be thrown in TemplateExtensions.SubstituteParams().

I can't turn off parameter substitution for this link, as I have one parameter that can be substituted and one that must be passed back as a parameter name to the client for substitution.

freeranger commented 6 years ago

Have you tried setting replaceParameters to false?

 AddLinks(new[] { new Link("order-link, "/orders/{id}, replaceParameters: false) });
alastairs commented 6 years ago

Thanks @freeranger. Yes, I managed to get this working with a mixture of replaceParameters: false and string interpolation, as in this example:

AddLinks(new[] {
    new Link(
        "order:shippingAddress",
        $"/orders/{orderId}/shipping/{{shippingAddressId}}",
        replaceParameters: false
    )});

String interpolation adds the order ID into the URL directly, and the double braces around shippingAddressId ensure that this remains as a parameter in the string, which is not then substituted by Halcyon thanks to replaceParameters: false as you suggested.

It would be helpful (and consistent with Halcyon's intended use, I think) if there were a way to specify within the URL string a parameter that should not be replaced when there is a mixture of some that can and some that cannot.

freeranger commented 6 years ago

There is though - what you are doing now with {param} or {{param}} gives you what you need. The alternative would be for halcyon to add some other string interpolation-like format to determine what should/should not be replaced, so instead of: $"/orders/{orderId}/shipping/{{shippingAddressId}}"

you'd end up with something like say: $"/orders/{orderId}/shipping/[shippingAddressId]"

Which then has to be parsed and turned into: $"/orders/1234/shipping/{shippingAddressId}"

Is that really any better? {} is the standard way of expressing parameters, and you don't have to use string interpolation (though it is nice) - it seems to me that halcyon is doing all it needs to, which is to render the string passed to it either replacing or not replacing parameters. How you generate the string to pass to it with the {parameters} is up to you...