DoLess.UriTemplates icon indicating copy to clipboard operation
DoLess.UriTemplates copied to clipboard

Multiple queries not merged on expand to string

Open DoCode opened this issue 7 years ago • 7 comments

Steps to reproduce

  • Example 1:
    var result = UriTemplate.For("https://localhost:5000/api/resource{?key,value}{?id,name}")
                            .WithPartialExpand()
                            .ExpandToString();
    
  • Example 2:
    var result = UriTemplate.For("https://localhost:5000/api/resource?key=mykey&value=myValue{?id,name}")
                            .WithPartialExpand()
                            .ExpandToString();
    

Expected behavior

  • Example 1:
    result == "https://localhost:5000/api/resource{?key,value}{&id,name}"
    
    or
    result == "https://localhost:5000/api/resource{?key,value,id,name}"
    
  • Example 2:
    result == "https://localhost:5000/api/resource?key=mykey&value=myValue{&id,name}"
    

Actual behavior

  • Example 1:
    result == "https://localhost:5000/api/resource{?key,value}{?id,name}"
    
  • Example 2:
    result == "https://localhost:5000/api/resource?key=mykey&value=myValue{?id,name}"
    

DoCode avatar Jun 22 '18 15:06 DoCode

Hi @DoCode. I didn't designed the partial expand to merge such templates. Why do you need such things?

To me, you should have these templates:

  • Example 1:
string uriString = UriTemplate.For("https://localhost:5000/api/resource{?key,value,id,name}")
                              .WithParameter("id", 10)
                              .WithPartialExpand()
                              .ExpandToString();
uriString.ShouldBeEquivalentTo("https://localhost:5000/api/resource?id=10{&key,value,name}");
  • Example 2:
string uriString = UriTemplate.For("https://localhost:5000/api/resource?key=mykey&value=myValue{&id,name}")
                              .WithParameter("id", 10)
                              .WithPartialExpand()
                              .ExpandToString();
uriString.ShouldBeEquivalentTo("https://localhost:5000/api/resource?key=mykey&value=myValue&id=10{&name}");

You can see here that the ? operator can be transformed to the & operator automatically if we partially expand a {?a,b,c} query with any of the parameter provided.

letsar avatar Jun 23 '18 07:06 letsar

Hi @letsar,
thanks for your response. I need such things because I used this in an ASP.NET Core API for HAL links. The UrlHelper creates the links as a preprocessor for specified routes and after that, your lib expands this strings with RFC6570 templates. The best would be when the library worked out of the box with the UrlHelper ;-)

DoCode avatar Jun 23 '18 12:06 DoCode

@DoCode thanks for this explanation. So if I understand correctly the UrlHelper creates url like "https://localhost:5000/api/resource{?key,value}{?id,name}"?

letsar avatar Jun 23 '18 14:06 letsar

@letsar sorry for the delay. No, I generate the links first, with the UrlHelper, based on the current request/response and then append the RFC6570 template parts with your libs.

DoCode avatar Jul 01 '18 11:07 DoCode

Ok so you generate the part {?key,value}{?id,name}? Why don't you generate {?key,value,id,name} instead ?

letsar avatar Jul 01 '18 14:07 letsar

The problem is, that I don't know if the existing (pre-rendered via UrlHelper) already contains a query. Like this code snippet:

protected override Task EnrichModel(INameBaseModel content, IUrlHelper urlHelper)
{
    RouteValueDictionary routeData = urlHelper.GetRouteDataWithQuery();

    ...

    new Link(
             HttpActionVerb.PUT,
             UriTemplate.For(urlHelper.Link(urlHelper.ActionContext.ActionDescriptor.AttributeRouteInfo.Name, routeData) + "{&value}")
                        .WithPartialExpand()
                        .ExpandToString(),
             RelationType.Self
            );


    ...
}

DoCode avatar Jul 01 '18 16:07 DoCode

Ok I understand now. UriTemplate must be a valid uri in the first place, so you will have to handle it yourself. If you want you can do that with an extension method and submit a pull request, so that it will be available for other people.

letsar avatar Jul 01 '18 17:07 letsar