Hypermedia links with Servicestack new API

前端 未结 1 980
旧巷少年郎
旧巷少年郎 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 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
    {
      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)
提交回复
热议问题