restasp.net-web-apihateoashypermediamedia-type

Links are empty in generated media type using WebApi.Hal


I am using WebApi.Hal to generate application/hal+json media type response from my ASP.Net Web API project. This is installed to the project using following nugget package manager command as outlined in WebApi.Hal 2.6.0

Install-Package WebApi.Hal

I created a request using postman and I received following response.

enter image description here

{
  "Id": 1,
  "Name": "blogEntryName",
  "StyleId": 1,
  "StyleName": "StylName",
  "_links": [],
  "_embedded": null
}

The links are coming as empty. How to get the links?

Global.asax

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            GlobalConfiguration.Configuration.Formatters.Add(new JsonHalMediaTypeFormatter());
            GlobalConfiguration.Configuration.Formatters.Add(new XmlHalMediaTypeFormatter());

        }

Controller and other classes

public class ValuesController : ApiController
    {

        public ValuesController()
        {

        }

        // GET api/values
        public BlogEntryRepresentation Get()
        {

            List<int> reviewIds = new List<int>();
            reviewIds.Add(1);
            reviewIds.Add(2);
            reviewIds.Add(3);

            BlogEntryRepresentation beerRep = new BlogEntryRepresentation
            {
                Id = 1,
                Name = "blogEntryName",

                StyleId = 1,
                StyleName = "StylName",
                ReviewIds = reviewIds
            };

            return beerRep;

        }        

    }

        public class BlogCategory
        {
            protected BlogCategory()
            {
            }

            public int Id { get; protected set; }
            public string Name { get; set; }
        }

        public class BlogEntry
        {
            protected BlogEntry()
            {
            }

            public BlogEntry(string name)
            {
                Name = name;
            }

            public int Id { get; protected set; }
            public string Name { get; set; }
            public BlogCategory Style { get; set; }

        }

        public class BlogEntryRepresentation : Representation
        {
            public int Id { get; set; }
            public string Name { get; set; }


            public int? StyleId { get; set; }
            public string StyleName { get; set; }

            [JsonIgnore]
            public List<int> ReviewIds { get; set; }

            public override string Rel
            {
                get { return LinkTemplates.BlogEntries.BlogEntry.Rel; }
                set { }
            }

            public override string Href
            {
                get { return LinkTemplates.BlogEntries.BlogEntry.CreateLink(new { id = Id }).Href; }
                set { }
            }

            protected override void CreateHypermedia()
            {
                if (StyleId != null)
                    Links.Add(LinkTemplates.BlogCategories.Style.CreateLink(new { id = StyleId }));

                if (ReviewIds != null && ReviewIds.Count > 0)
                    foreach (var rid in ReviewIds)
                        Links.Add(LinkTemplates.Reviews.GetBeerReview.CreateLink(new { id = Id, rid }));
            }
        }

public static class LinkTemplates
    {

        public static class BlogCategories
        {
            public static Link GetStyles { get { return new Link("styles", "~/styles"); } }
            public static Link AssociatedBlogEntries { get { return new Link("blogEntries", "~/styles/{id}/blogEntries{?page}"); } }
            public static Link Style { get { return new Link("style", "~/styles/{id}"); } }
        }

        public static class BlogEntries
        {
            public static Link GetBlogEntries { get { return new Link("blogEntries", "~/blogEntries{?page}"); } }
            public static Link SearchBeers { get { return new Link("page", "~/blogEntries{?searchTerm,page}"); } }
            public static Link BlogEntry { get { return new Link("blogEntry", "~/blogEntries/{id}"); } }
        }

        public static class Reviews
        {
            public static Link GetBeerReview { get { return new Link("review", "~/blogEntries/{id}/reviews/{rid}"); } }
        }
}

REFERENCES

  1. Top 20 NuGet packages for hypermedia
  2. Popular C# HAL Projects

Solution

  • I found the issue - I should have used Accept header.

    Server can support hal+json, hal+xml, and ordinary json. The client can use Accept header to tell which one it wants.

    "Content-Type" means the format of the actual payload, if any. The request has no payload, so Content-Type is ignored.

    enter image description here