Let’s begin with the concept we know so far, and that’s the link. In the Domain
project, we are going to create the LinkModels
folder and inside a new Link
class:
public class Link { public string? Href { get; set; } public string? Rel { get; set; } public string? Method { get; set; } public Link() { } public Link(string href, string rel, string method) { Href = href; Rel = rel; Method = method; } }
Note that we have an empty constructor, too. We’ll need that for XML serialization purposes, so keep it that way. Next, in the same folder, we need to create a class that will contain all of our links — LinkResourceBase
:
public class LinkResourceBase { public LinkResourceBase() { } public List<Link> Links { get; set; } = new List<Link>(); }
Finally, since our response needs to describe the root of the controller, we need a wrapper for our links in the same folder:
public class LinkCollectionWrapper<T> : LinkResourceBase { public List<T> Value { get; set; } = new List<T>(); public LinkCollectionWrapper() { } public LinkCollectionWrapper(List<T> value) => Value = value; }
This class might not make too much sense right now, but stay with us and it will become clear later down the road. For now, let’s just assume we wrapped our links in another class for response representation purposes. Since our response will contain links too, we need to extend the XML serialization rules so that our XML response returns the properly formatted links.
Without this, we would get something like: <Links>System.Collections.Generic.List`1[Entites.Models.Link]<Links>
.
So, in the Domain/Models/Entity
class, we need to extend the WriteLinksToXml
method to support links:
private void WriteLinksToXml(string key, object value, XmlWriter writer) { writer.WriteStartElement(key); if (value.GetType() == typeof(List<Link>)) { foreach (var val in value as List<Link>) { writer.WriteStartElement(nameof(Link)); WriteLinksToXml(nameof(val.Href), val.Href, writer); WriteLinksToXml(nameof(val.Method), val.Method, writer); WriteLinksToXml(nameof(val.Rel), val.Rel, writer); writer.WriteEndElement(); } } else { writer.WriteString(value.ToString()); } writer.WriteEndElement(); }
So, we check if the type is List<Link>
. If it is, we iterate through all the links and call the method recursively for each of the properties: href, method, and rel. That’s all we need for now. We have a solid foundation to implement HATEOAS in our project.