0

I am creating an API for project tasks. It has a TasksController as listed below. I am generating hypermedia using WebApi.Hal and the service supports hal+json and hal+xml media types also.

Following is the response I currently have for the GET request http://localhost:51910/api/tasks/1. In the response there is a list of links for priorities – but they don’t have associated name in the response (to show in the UI – like Low, Medium, High, etc.).

What is the best HAL approach for getting name of the priorities also, using WebApi.HAL?

Note: The list of priorities can be enhanced in the future.

enter image description here

Priority

public class Priority
{
    public int PriorityID { get; set; }
    public string PriorityName { get; set; }
    public string Revision { get; set; }
    public DateTime ApprovalDate { get; set; }
}

Controller

public class TasksController : ApiController
    {
        // GET api/values/5
         [HttpGet]
        public TaskRepresentation Get(int id)
        {

            Task selectedTask = TasksHelper.GetTask(id);
            TaskRepresentation taskRepresentation = new TaskRepresentation(selectedTask);
            return taskRepresentation;
        }

        //PUT For Setting Priority
        [HttpPut]
        [Route("api/tasks/{taskID}/priorities/{priorityID}")]
        public TaskRepresentation PutSetPriority(int taskID, int priorityID)
        {
            Task selectedTask = TasksHelper.GetTask(taskID);

            Priority selectedPriority = null;
            List<Priority> allPriorities = TasksPrioritiesHelper.GetAllPriorities();
            foreach (Priority p in allPriorities)
            {
                if (p.PriorityID == priorityID)
                {
                    selectedPriority = p;
                }
            }

            //Update Task
            if (selectedPriority != null)
            {
                selectedTask.CurrentPriority = selectedPriority.PriorityName;
            }
            else
            {

                throw new Exception("Not available");
            }


            TaskRepresentation taskRepresentation = new TaskRepresentation(selectedTask);
            return taskRepresentation;
        }

        [HttpGet]
        [Route("api/tasks/{taskID}/priorities/{priorityID}")]
        public Priority Get(int taskID, int priorityID)
        {
            Priority selectedPriority = null;
            List<Priority> allPriorities = TasksPrioritiesHelper.GetAllPriorities();
            foreach (Priority p in allPriorities)
            {
                if (p.PriorityID == priorityID)
                {
                    selectedPriority = p;
                }
            }

            return selectedPriority;
        }

    }

HAL Generation Related Classes

public static class LinkTemplates
    {

        public static class TaskLinks
        {
            public static Link TaskEntry { get { return new Link("self", "~/api/tasks/{taskID}"); } }
            public static Link PriorityLink { get { return new Link("priorities", "~/api/tasks/{taskID}/priorities/{priorityID}"); } }
        }
    }

public class TaskRepresentation : Representation
    {
        Task theTask;

        public int TaskID{get{return theTask.TaskID;}}
        public string TaskName{get{return theTask.Name;}}
        public string CurrentPriority{get{return theTask.CurrentPriority;}}
        public string Category{get{return theTask.Category;}}

        public TaskRepresentation(Task t)
        {
            theTask = t;
        }


        public override string Rel
        {
            get { return LinkTemplates.TaskLinks.TaskEntry.Rel; }
            set { }
        }

        public override string Href
        {
            get { return LinkTemplates.TaskLinks.TaskEntry.CreateLink(new { taskID = theTask.TaskID }).Href; }
            set { }
        }


        protected override void CreateHypermedia()
        {
            foreach (Priority p in theTask.PossiblePriorities)
            {
                Links.Add(LinkTemplates.TaskLinks.PriorityLink.CreateLink(new { taskID = theTask.TaskID, priorityID = p.PriorityID }));
            }
        }
    }
LCJ
  • 22,196
  • 67
  • 260
  • 418

1 Answers1

0

HAL Specification mentions title - this will meet the requirement.

Following is the updated response.

{
  "TaskID": 1,
  "TaskName": "Task1",
  "CurrentPriority": "Medium",
  "Category": "IT",
  "_links": {
    "self": {
      "href": "/api/tasks/1"
    },
    "priorities": [
      {
        "href": "/api/tasks/1/priorities/101",
        "title": "Low"
      },
      {
        "href": "/api/tasks/1/priorities/103",
        "title": "High"
      },
      {
        "href": "/api/tasks/1/priorities/104",
        "title": "Critical"
      }
    ]
  }
}

WebAPI.HAL changes

protected override void CreateHypermedia()
        {
            foreach (Priority p in theTask.PossiblePriorities)
            {
                Link lnk = LinkTemplates.TaskLinks.PriorityLink.CreateLink(new { taskID = theTask.TaskID, priorityID = p.PriorityID });
                lnk.Title = p.PriorityName;
                Links.Add(lnk);
            }
        }

Code

public static class LinkTemplates
    {

        public static class TaskLinks
        {
            public static Link TaskEntry { get { return new Link("self", "~/api/tasks/{taskID}"); } }
            //public static Link PriorityLink { get { return new Link("priorities", "~/api/tasks/{taskID}/priorities/{priorityID}"); } }
            public static Link PriorityLink 
            { 
                get 
                {
                    Link l = new Link("priorities", "~/api/tasks/{taskID}/priorities/{priorityID}");
                    return l;
                } 
            }
        }
    }


    public class TasksController : ApiController
    {
        // GET api/values/5
         [HttpGet]
        public TaskRepresentation Get(int id)
        {

            Task selectedTask = TasksHelper.GetTask(id);
            TaskRepresentation taskRepresentation = new TaskRepresentation(selectedTask);
            return taskRepresentation;
        }

        //PUT For Setting Priority
        [HttpPut]
        [Route("api/tasks/{taskID}/priorities/{priorityID}")]
        public TaskRepresentation PutSetPriority(int taskID, int priorityID)
        {
            Task selectedTask = TasksHelper.GetTask(taskID);

            Priority selectedPriority = null;
            List<Priority> allPriorities = TasksPrioritiesHelper.GetAllPriorities();
            foreach (Priority p in allPriorities)
            {
                if (p.PriorityID == priorityID)
                {
                    selectedPriority = p;
                }
            }

            //Update Task
            if (selectedPriority != null)
            {
                selectedTask.CurrentPriority = selectedPriority.PriorityName;
            }
            else
            {

                throw new Exception("Not available");
            }


            TaskRepresentation taskRepresentation = new TaskRepresentation(selectedTask);
            return taskRepresentation;
        }

        [HttpGet]
        [Route("api/tasks/{taskID}/priorities/{priorityID}")]
        public Priority Get(int taskID, int priorityID)
        {
            Priority selectedPriority = null;
            List<Priority> allPriorities = TasksPrioritiesHelper.GetAllPriorities();
            foreach (Priority p in allPriorities)
            {
                if (p.PriorityID == priorityID)
                {
                    selectedPriority = p;
                }
            }

            return selectedPriority;
        }

    }

    public class TaskRepresentation : Representation
    {
        Task theTask;

        public int TaskID{get{return theTask.TaskID;}}
        public string TaskName{get{return theTask.Name;}}
        public string CurrentPriority{get{return theTask.CurrentPriority;}}
        public string Category{get{return theTask.Category;}}

        public TaskRepresentation(Task t)
        {
            theTask = t;
        }


        public override string Rel
        {
            get { return LinkTemplates.TaskLinks.TaskEntry.Rel; }
            set { }
        }

        public override string Href
        {
            get { return LinkTemplates.TaskLinks.TaskEntry.CreateLink(new { taskID = theTask.TaskID }).Href; }
            set { }
        }


        protected override void CreateHypermedia()
        {
            foreach (Priority p in theTask.PossiblePriorities)
            {
                Link lnk = LinkTemplates.TaskLinks.PriorityLink.CreateLink(new { taskID = theTask.TaskID, priorityID = p.PriorityID });
                lnk.Title = p.PriorityName;
                Links.Add(lnk);
            }
        }
    }

    public class Task
    {
        public string Name { get; set; }
        public int TaskID { get; set; }
        public string Category { get; set; }
        public string CurrentPriority  { get; set; }
        public List<Priority> PossiblePriorities { get; set; }
    }
    public class Priority
    {
        public int PriorityID { get; set; }
        public string PriorityName { get; set; }
        public string Revision { get; set; }
        public DateTime ApprovalDate { get; set; }
    }

    public static class TasksPrioritiesHelper
    {

        public static List<Priority> GetAllPriorities()
        {
            List<Priority> possiblePriorities = new List<Priority>();
            Priority pLow = new Priority { PriorityID = 101, PriorityName = "Low" };
            Priority pMedium = new Priority { PriorityID = 102, PriorityName = "Medium" };
            Priority pHigh = new Priority { PriorityID = 103, PriorityName = "High" };
            Priority pCritical = new Priority { PriorityID = 104, PriorityName = "Critical" };

            possiblePriorities.Add(pLow);
            possiblePriorities.Add(pMedium);
            possiblePriorities.Add(pHigh);
            possiblePriorities.Add(pCritical);

            return possiblePriorities;
        }

        public static List<Priority> GetAdministrativePriorities()
        {
            List<Priority> possiblePriorities = new List<Priority>();
            Priority pLow = new Priority { PriorityID = 101, PriorityName = "Low" };
            Priority pHigh = new Priority { PriorityID = 103, PriorityName = "High" };

            possiblePriorities.Add(pLow);
            possiblePriorities.Add(pHigh);

            return possiblePriorities;
        }


        public static List<Priority> GetPossiblePrioritiesForTask(Task t)
        {
            List<Priority> possibleTaskPriorities = new List<Priority>();


            if (String.Equals(t.Category, "IT"))
            {
                possibleTaskPriorities = GetAllPriorities();
            }
            else
            {
                possibleTaskPriorities = GetAdministrativePriorities();
            }

            Priority currentTaskPriority = null;
            foreach(Priority p in possibleTaskPriorities )
            {
                if(String.Equals(t.CurrentPriority,p.PriorityName ))
                {
                    currentTaskPriority=p;
                }
            }

            if(currentTaskPriority!=null)
            {
                possibleTaskPriorities.Remove(currentTaskPriority);
            }


            return possibleTaskPriorities;
        }


    }
    public static class TasksHelper
    {
        public static Task GetTask(int id)
        {
            Task selectedTask = null;
            List<Task> tasks = GetAllTasks();

            foreach (Task t in tasks)
            { 
                if(t.TaskID==id)
                {
                    selectedTask = t;
                }
            }
            return selectedTask;
        }


        public static List<Task> GetAllTasks()
        {

            List<Task> tasks;
            tasks = new List<Task>();

            Task t1 = new Task{Category = "IT",CurrentPriority = "Medium",Name = "Task1",TaskID = 1};
            t1.PossiblePriorities = TasksPrioritiesHelper.GetPossiblePrioritiesForTask(t1);

            tasks.Add(t1);

            return tasks;
        }


    }
LCJ
  • 22,196
  • 67
  • 260
  • 418