{"id":13429500,"url":"https://github.com/visualeyes/halcyon","last_synced_at":"2026-01-16T07:53:47.466Z","repository":{"id":60774046,"uuid":"42553255","full_name":"visualeyes/halcyon","owner":"visualeyes","description":"A HAL implementation for ASP.NET","archived":false,"fork":false,"pushed_at":"2018-10-07T20:32:11.000Z","size":203,"stargazers_count":81,"open_issues_count":15,"forks_count":29,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-07T13:06:25.024Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/visualeyes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-15T23:40:31.000Z","updated_at":"2024-04-07T09:08:50.000Z","dependencies_parsed_at":"2022-10-04T15:30:41.638Z","dependency_job_id":null,"html_url":"https://github.com/visualeyes/halcyon","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/visualeyes%2Fhalcyon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/visualeyes%2Fhalcyon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/visualeyes%2Fhalcyon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/visualeyes%2Fhalcyon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/visualeyes","download_url":"https://codeload.github.com/visualeyes/halcyon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243822310,"owners_count":20353496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T02:00:40.784Z","updated_at":"2026-01-16T07:53:47.425Z","avatar_url":"https://github.com/visualeyes.png","language":"C#","funding_links":[],"categories":["Frameworks, Libraries and Tools","框架, 库和工具","API"],"sub_categories":["API"],"readme":"# Halcyon \n![Build Status](https://ci.appveyor.com/api/projects/status/github/visualeyes/halcyon?branch=master\u0026svg=true) \n[![Coverage Status](https://coveralls.io/repos/visualeyes/halcyon/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/visualeyes/halcyon?branch=master)\n\n**Halcyon** - \n[![Halcyon Nuget Version](https://img.shields.io/nuget/v/Halcyon.svg)](https://www.nuget.org/packages/Halcyon/) \n[![Halcyon Nuget Version](https://img.shields.io/nuget/vpre/Halcyon.svg)](https://www.nuget.org/packages/Halcyon/) \n\n**Halcyon.WebApi** *(ASP.NET Web API)* - \n[![Halcyon.WebApi Nuget Version](https://img.shields.io/nuget/v/Halcyon.WebApi.svg)](https://www.nuget.org/packages/Halcyon.WebApi/)\n[![Halcyon.WebApi Nuget Version](https://img.shields.io/nuget/vpre/Halcyon.WebApi.svg)](https://www.nuget.org/packages/Halcyon.WebApi/)\n\n**Halcyon.Mvc** *(ASP.NET Core)* -\n[![Halcyon.WebApi Nuget Version](https://img.shields.io/nuget/v/Halcyon.Mvc.svg)](https://www.nuget.org/packages/Halcyon.Mvc/)\n[![Halcyon.WebApi Nuget Version](https://img.shields.io/nuget/vpre/Halcyon.Mvc.svg)](https://www.nuget.org/packages/Halcyon.Mvc/)\n\n\nA HAL implementation for ASP.NET. Halcyon builds a HAL Model and lets ASP.NET take care of formatting the model into JSON.\n\n## What is HAL?\n\u003e HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API.\n\nFor more information please see [the guide](https://github.com/mikekelly/hal_specification) and [the formal sepcification](http://stateless.co/hal_specification.html)\n\n## Why Halcyon?\n\nHalcyon was created with to meet two core requirements:\n\n* The client should be able to chose whether or not to use HAL. The controller should return HAL or plain JSON based on the accept header. \n* The developer should not have to significantly modify Models to return HAL formatted JSON\n\n\n\nFor more info you can read the [blog post](https://medium.com/@johncmckim/halcyon-hal-for-net-ebc416844152)\n\n## Getting Started with Halcyon\n\n**Getting Halcyon**\n\nFor ASP.NET 4.5 - `Install-Package Halcyon.WebApi`\n\nIf you are using ASP.NET Core - `Install-Package Halcyon.Mvc -Pre`\n\n**Using Halcyon**\n\nHalcyon is simple to drop into an exising project as it does not require changes to existing models.\nTo start returing HAL from you API you simply need to call the HAL method in your Controller.\n```c#\nreturn HAL(model, new Link[] {\n    new Link(\"self\", \"/api/foo/{id}\"),\n    new Link(\"foo:bar\", \"/api/foo/{id}/bar\")\n});\n```\nIf you want more flexibility you can build a HALResponse using the Fluent API\n```c#\nvar response = new HALResponse(model)\n                .AddLinks(linkOne)\n                .AddLinks(linkTwo)\n                .AddEmbeddedCollection(embeddedName, embedded);\n    \nreturn this.Ok(response);\n```\n## Upgrading from 1.0 to 1.1\n\n## Full Example\nLinks add discoverability by directing consumers to other Resources in the API.\nThe self link is a special link that references the current resource.\n\n#### Controller \n```c#\n[RoutePrefix(\"api/foo\")]\npublic class FooController : Controller {\n    \n    [HttpGet, Route(\"{id:int}\")]\n    public IActionResult Get(int id) {\n        // Any plain old object will do\n        var fooModel = new {\n            id = id,\n            type = \"foo\"\n        };\n            \n        // Return a simple resource with links to related resources\n        return this.HAL(fooModel, new Link[] {\n            new Link(\"self\", \"/api/foo/{id}\"),\n            new Link(\"foo:bar\", \"/api/foo/{id}/bar\")\n        });\n    }\n    \n    [HttpGet, Route(\"{fooId:int}/bars\")]\n    public IActionResult GetBar(int fooId) {\n        // A collection of bars related to foo\n        var bars = new List\u003cobject\u003e {\n            new { id = 1, fooId = fooId, type = \"bar\" },\n            new { id = 2, fooId = fooId, type = \"bar\" }\n        };\n    \n        // data about the bars related to foo\n        var fooBarModel = new {\n            fooId = fooId,\n            count = bars.Count\n        };\n    \n        // Return a fooBar resource with embedded bars\n        return this.HAL(\n            fooBarModel,\n            new Link[] {\n                new Link(\"self\", \"/api/foo/{fooId}/bar\")\n            },\n            \"bars\",\n            bars,\n            new Link[] {\n                new Link(\"self\", \"/api/bar/{id}\")\n            }\n        );\n    }\n}\n```\n#### Results\n\n##### /api/foo/1\n```json\n{\n  \"_links\": {\n    \"self\": {\n      \"href\": \"/api/foo/1\"\n    },\n    \"foo:bar\": {\n      \"href\": \"/api/foo/1/bar\"\n    }\n  },\n  \"id\": 1,\n  \"type\": \"foo\"\n}\n```\n##### /api/foo/1/bar\n```json\n{\n  \"_links\": {\n    \"self\": {\n      \"href\": \"/api/foo/1/bar\"\n    }\n  },\n  \"_embedded\": {\n    \"bars\": [{\n     \"_links\": {\n        \"self\": {\n          \"href\": \"/api/foo/1\"\n        }\n      },\n      \"id\": 1,\n      \"fooId\": 1, \n      \"type\": \"bar\"\n    },{\n      \"_links\": {\n        \"self\": {\n          \"href\": \"/api/foo/2\"\n        }\n      },\n      \"id\": 2,\n      \"fooId\": 1, \n      \"type\": \"bar\"\n    }]\n  },\n  \"fooId\": 1,\n  \"count\": \"2\"\n}\n```\n## Accept Header\n\nBy default HAL method returns HAL formatted responses regardless of the Accept Header.\nIf you need to return both HAL and standard JSON you can configure this using a ``JsonHALMediaTypeFormatter`` or ``JsonHalOutputFormatter```\ndepending on your version of MVC.\n\n**MVC 5 and earlier**\n\n```c#\nconfig.Formatters.RemoveAt(0);\nconfig.Formatters.Insert(0, new JsonHALMediaTypeFormatter(\n    halJsonMediaTypes: new string[] { \"application/hal+json\", \"application/vnd.example.hal+json\", \"application/vnd.example.hal.v1+json\" },\n    jsonMediaTypes: new string[] { \"application/vnd.example+json\", \"application/vnd.example.v1+json\" }\n));\n```\n\n** MVC 6 and later**\n\n```c#\npublic IServiceProvider ConfigureServices(IServiceCollection services) {\n    services\n      .AddMvc()\n      .AddMvcOptions(c =\u003e {\n          c.OutputFormatters.RemoveType\u003cJsonOutputFormatter\u003e();\n          c.OutputFormatters.Add(new JsonHalOutputFormatter(\n              new string[] { \"application/hal+json\", \"application/vnd.example.hal+json\", \"application/vnd.example.hal.v1+json\" }\n          ));\n      })\n}\n```\nThis will return responses without the HAL properties for requests that send an Accept Type included in the ``jsonMediaTypes`` array.\nEmbedded collections will be attached at the root of the JSON Object.\n\n```json\n{\n  \"fooId\": 1,\n  \"count\": 2,\n  \"bars\": [\n    {\n      \"id\": 1,\n      \"fooId\": 1,\n      \"type\": \"bar\"\n    },\n    {\n      \"id\": 2,\n      \"fooId\": 1,\n      \"type\": \"bar\"\n    }\n  ]\n}\n```\n\n## Compatability with HALON\n[Halon](https://github.com/LeanKit-Labs/halon) is a HAL Javascript client that adds non-standard properties.\n\nWhen creating a link you can optionally set the Method property to provide compatability with this client\n\n\n## Credits\nThis project was inspiried by https://github.com/JakeGinnivan/WebApi.Hal. \nThe fundamental difference is that Halcyon does not require large changes \nto your models to function.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvisualeyes%2Fhalcyon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvisualeyes%2Fhalcyon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvisualeyes%2Fhalcyon/lists"}