Hypermedia links with Servicestack new API

前端 未结 1 979
旧巷少年郎
旧巷少年郎 2021-01-05 11:33

I am evaluating how to add hypermedia links to DTO responses. Although there is no standard, add List to the response DTOs seems to be the suggested approach.

Do yo

相关标签:
1条回答
  • 2021-01-05 12:12

    The way I do this currently is I pass back a response dto which implements an interface

    public interface IHaveLinks
    {
      [IgnoreDataMember]
      IEnumerable<Link> Links { get; }
    }
    
    public class Link
    {
      public string Name { get; set; }
      public IReturn Request { get; set; }
      public string Method { get; set; }
    }
    

    Then I use a response filter to generate the urls and populate the response headers with the links.

    this.ResponseFilters.Add((req, res, dto) =>
    {
      if (!(dto is IHaveLinks))
        return;
    
      var links = (dto as IHaveLinks).Links
    
      if(links == null || !links.Any())
        return;
    
      var linksText = links
        .Select(x => string.Format("<{0}>; rel={1}"), x.Request.ToUrl(x.Method), x.Name));
    
      var linkHeader = string.Join(", ", linksText);
    
      res.AddHeader("Link", linkHeader);
    });
    

    This seems the cleanest way. The Link object above effectively says "If you make this request with this method you will get back the named resource". The only HTTP thing that bleeds up to the BLL is Method. But you could get rid of that and only pass back GET urls. Or map it to some generalised "operation"?

    As an example:

    public class ExampleService : Service
    {
      public ExamplesResponse Get(ExamplesRequest request)
      {
        var page = request.Page;
        var data = // get data;
    
        return new ExamplesResponse
          {
            Examples = data,
            Links = new []
              {
                new Link { Name = "next", Request = request.AddPage(1), Method = "GET" },
                new Link { Name = "previous", Request = request.AddPage(-1), Method = "GET" },
              }
          }
      }
    }
    
    [Route("/examples/{Page}")]
    public class ExamplesRequest : IReturn<ExamplesResponse>
    {
      public int Page { get; set; }
    
      // ...
    }
    

    (The AddPage method returns a clone of the request and sets the Page property appropriately.)

    Hope that helps.

    0 讨论(0)
提交回复
热议问题