在 c# webapi 中创建超媒体的正确方法

Proper approach to create hypermedia in c# webapi

我正在研究如何为特定资源实施超媒体,但找不到真正的实施示例,只是抽象...

你知道,在各种文章中,这个人创建了如下方法:

public List<Link> CreateLinks(int id)
{
    ...//Here the guy put these three dots, whyyyyyyyyyy?
}

我目前拥有的:

public Appointment Post(Appointment appointment)
    {
        //for sake of simplicity, just returning same appointment
        appointment = new Appointment{
            Date = DateTime.Now,
            Doctor = "Dr. Who",
             Slot = 1234,
            HyperMedia = new List<HyperMedia>
            {
                new HyperMedia{ Href = "/slot/1234", Rel = "delete" },
                new HyperMedia{ Href = "/slot/1234", Rel = "put" },
            }
        };

        return appointment;
    }

和约会class:

public class Appointment
{
    [JsonProperty("doctor")]
    public string Doctor { get; set; }

    [JsonProperty("slot")]
    public int Slot { get; set; }
    [JsonProperty("date")]
    public DateTime Date { get; set; }

    [JsonProperty("links")]
    public List<HyperMedia> HyperMedia { get; set; }
}

public class HyperMedia
{
    [JsonProperty("rel")]
    public string Rel { get; set; }

    [JsonProperty("href")]
    public string Href { get; set; }
}

有正确的方法吗?我的意思是,没有对链接进行硬编码?如何为给定类型动态创建它们,即约会 class?

我使用的是 c# Webapi,而不是 c# MVC。

您绝对可以将 Rel 提取到 Enum(实际上是标准的 2 - DeletePut 等 - 以及自定义的 -后者可以包含自定义关系,例如 customer-by-id).

您还可以动态构建 Href 参数(从对象的属性中提取参数),但至于资源本身......您可能坚持使用硬编码(您也可以查看反思)。

  1. 要将路由动态添加到 HyperMedia 集合,您可以使用路由命名:

    • 使用特定名称定义您的路线(例如删除):

      [Route("{id:int}", Name = "AppointmentDeletion")]
      public IHttpActionResult Delete(int slot)
      {
          //your code
      }
      
    • 使用方法UrlHelper.Link:

      public Appointment Post(Appointment appointment)
      {
          appointment = new Appointment
          {
              HyperMedia = new List<HyperMedia>
              {
                  new HyperMedia
                  { 
                      Href = Url.Link("AppointmentDeletion", new { slot = 1234 }), 
                      Rel = "delete" 
                  }
              }
      
          return appointment;
      }; 
      
  2. 也可以在不为每个 class:

    声明 HyperMedia 属性 的情况下动态添加链接到结果对象
    • 定义一个没有链接的class:

      public class Appointment
      {
          [JsonProperty("doctor")]
          public string Doctor { get; set; }
      
          [JsonProperty("slot")]
          public int Slot { get; set; }
      
          [JsonProperty("date")]
          public DateTime Date { get; set; }
      } 
      
    • 定义扩展方法:

      public static class LinkExtensions
      {
          public static dynamic AddLinks<T>(this T content, params object[] links)
          {
              IDictionary<string, object> result = new ExpandoObject();
      
              typeof (T)
                  .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                  .ToList()
                  .ForEach(_ => result[_.Name.ToLower()] = _.GetValue(content));
      
              result["links"] = links;
      
              return result;
          }
      }
      
    • 使用它:

      public IHttpActionResult Post(Appointment appointment)
      {
          return Ok(appointment.AddLinks(new HyperMedia
          { 
              Href = Url.Link("AppointmentDeletion", new { slot = 1234 }), 
              Rel = "delete" 
          }));
      }