Правильный подход к созданию гипермедиа в 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;
}
И Назначение класса:
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; }
}
Есть ли правильный путь к этому? Я имею в виду, без жесткого кодирования ссылок? Как создать их динамически для заданного типа, т.е. класса назначений?
Я использую C# Webapi, а не C# MVC.
2 ответа
Для динамического добавления маршрутов в коллекцию 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; };
Также возможно динамически добавлять ссылки на результирующий объект, не объявляя свойство HyperMedia для каждого класса:
Определите класс без ссылок:
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" })); }
Вы можете определенно извлечь Rel
в Enum
(2 на самом деле, стандартный - Delete
, Put
и т. д. - и пользовательский - последний может содержать пользовательские отношения, такие как customer-by-id
).
Вы также можете построить Href
параметры динамически (извлекают параметры из свойств объекта), но что касается самого ресурса... вы, вероятно, застряли с жестким кодированием (вы также можете посмотреть на отражение).