{"id":21528447,"url":"https://github.com/hellokitty/typesafe.http.net","last_synced_at":"2025-04-09T23:42:35.611Z","repository":{"id":65414243,"uuid":"95397498","full_name":"HelloKitty/TypeSafe.Http.Net","owner":"HelloKitty","description":"A typesafe HTTP library for .NET Framework, .NET Core and .NET Standard. Brings type safety to web.","archived":false,"fork":false,"pushed_at":"2018-07-06T01:05:59.000Z","size":139,"stargazers_count":7,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T01:35:31.927Z","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":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HelloKitty.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":"2017-06-26T01:43:48.000Z","updated_at":"2020-04-28T17:43:56.000Z","dependencies_parsed_at":"2023-01-23T10:55:11.639Z","dependency_job_id":null,"html_url":"https://github.com/HelloKitty/TypeSafe.Http.Net","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HelloKitty%2FTypeSafe.Http.Net","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HelloKitty%2FTypeSafe.Http.Net/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HelloKitty%2FTypeSafe.Http.Net/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HelloKitty%2FTypeSafe.Http.Net/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HelloKitty","download_url":"https://codeload.github.com/HelloKitty/TypeSafe.Http.Net/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248131470,"owners_count":21052819,"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-11-24T01:53:20.589Z","updated_at":"2025-04-09T23:42:35.590Z","avatar_url":"https://github.com/HelloKitty.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TypeSafe.Http.Net\n\nTypeSafe.Http.Net is an automatic type-safe REST web client. Bringing type safety to the uncertainty of web.\n\nTypeSafe.Http.Net is a heavily inspired by Square's [Retrofit library](http://square.github.io/retrofit/) and Paul Betts' [Refit library](https://github.com/paulcbetts/refit). It turns your REST or ASP.NET Web APIs into type-safe async RPCs (remote procedural calls):\n\n## Features\n- [ ] **Performance** (library is not yet profiled/optimized)\n- [x] **Netstandard1.4**\n- [x] **Net45**\n- [x] Type Headers\n- [x] Method Headers\n- [x] Dynamic Header Values/Formatting\n- [x] Action Paths\n- [x] Dynamic Action Paths\n- [x] JSON Serialization/Deserialization\n- [x] URL Encoded Body Serialization/Deserialization\n- [ ] URL Encoded Dictionary Serialization/Deserialization\n- [x] Protobuf Serialization/Deserialization\n- [x] .NET Framework XML Serializer Serialization/Deserialization\n- [ ] Multipart\n- [ ] Stream Content\n- [x] [.NET HttpClient Implementation](https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx)\n- [x] [RestSharp Implementation](https://github.com/restsharp/RestSharp)\n\n## How to Use\n\nTypeSafe.Http.Net is designed for ease-of-use. Using the modern concept of reflection, metadata or annotations you can prepare a .NET interface type to become a client to a REST/HTTP/Web service.\n\n```csharp\nIServiceInterface service = TypeSafeHttpBuilder\u003cIServiceInterface\u003e().Create()\n  .RegisterDefaultSerializers()\n\t.RegisterDotNetHttpClient(@\"http://localhost:5000\")\n\t.RegisterJsonNetSerializer()\n\t.Build();\n```\n\nTo prepare an interface for use in TypeSafe.Http.Net you'll want to add the NuGet Package [TypeSafe.Http.Net.Metadata](https://www.nuget.org/packages/TypeSafe.Http.Net.Metadata/) that contains the attributes/annotations for the project. The Metadata project currently has a requirement of Netstandard1.1 but I am working on reducing this to Netstandard1.0.\n\n### Http Methods\n\nOnce included you will be able to reference all of the standard attributes in the TypeSafe.Http.Net project. Of particular importance you'll want to see the [HttpMethod Attributes](https://github.com/HelloKitty/TypeSafe.Http.Net/tree/master/src/TypeSafe.Http.Net.Metadata/Attributes/Methods). For out first example we will be using a GET request.\n\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  Task Test()\n}\n```\n\nResult of calling Test:\n\n```\nGET {baseurl}/api/test\n```\n\nThe ability to control the endpoint/action dynamically, which is required for a REST service, is simple to take advantage of. All you need is to utilize formatted strings and provide parameters to the Test method. You can insert values into the action path like so.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/{id}/test\")]\n  Task Test(int id)\n}\n```\n\nResult of calling Test:\n\n```\nGET {baseurl}/api/{id}/test\n```\n\nWhere {id} is for example 5 if you make a call to the interface like so service.Test(5).\n\nIf you want to use a parameter name differing from the string format indicator then you can utilize [AliasAs](https://github.com/HelloKitty/TypeSafe.Http.Net/blob/master/src/TypeSafe.Http.Net.Metadata/Attributes/AliasAsAttribute.cs) Attribute. This attribute allows to essentially rename a parameter. It works with querystrings, action paths and even UrlEncodedBody serialization.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/{id}/test\")]\n  Task Test([AliasAs(\"id\")] int identifier)\n}\n```\n\nResult of calling Test:\n\n```\nGET {baseurl}/api/{id}/test\n```\n\n### Headers\n\nIf we wanted to add static headers to the all the methods on this service interface we can use another attribute called [Header](https://github.com/HelloKitty/TypeSafe.Http.Net/blob/master/src/TypeSafe.Http.Net.Metadata/Attributes/HeaderAttribute.cs).\n\n```csharp\n[Header(\"User-Agent\", \"TestClient 1.0\")]\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  Task Test()\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test\nUser-Agent: TestClient 1.0\n```\n\nIf you want to add a header to only a specifc method and not all methods on a service then you can annotate that specific method instead.\n\n```csharp\n[Header(\"User-Agent\", \"TestClient 1.0\")]\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  [Header(\"Custom-Header\", \"Test1\", \"Test2\")]\n  Task Test()\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test\nUser-Agent: TestClient 1.0\nCustom-Header: Test1, Test2\n```\n\nIt is also ok to have multiple of the same header annotation. The values will be combined however the order in which these header values will appear is not defined. Make no expectation of that.\n\n```csharp\n[Header(\"User-Agent\", \"TestClient 1.0\")]\n[Header(\"Custom-Header\", \"Test5\", \"Test6\")]\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  [Header(\"Custom-Header\", \"Test1\", \"Test2\")]\n  [Header(\"Custom-Header\", \"Test3\", \"Test4\")]\n  Task Test()\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test\nUser-Agent: TestClient 1.0\nCustom-Header: Test1, Test2, Test3, Test4, Test5, Test6\n```\n\nDynamic headers are a planned feature but not yet supported.\n\n### Query String Parameters\n\nTypeSafe.Http.Net also supports querystring parameters in multiple ways. The most basic way is a static querystring parameter.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test?param1=1\u0026param2=2\")]\n  Task Test()\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test?param1=1\u0026param2=2\n```\n\nAnother way is to utilize the [QueryStringParameter](https://github.com/HelloKitty/TypeSafe.Http.Net/blob/master/src/TypeSafe.Http.Net.Metadata/Attributes/Serialization/QueryStringParameterAttribute.cs) attribute like the following.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test?param1=1\u0026param2=2\")]\n  Task Test([QueryStringParameter] string t)\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test?param1=1\u0026param2=2\u0026t={t}\n```\n\n{t} will be the value of the string provided during the method call. It is essentially effortless. You do not need to worry about existing querystring parameters or even if you have none. The querystring will be built for you.\n\nSome more examples.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  Task Test([QueryStringParameter] string test)\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test?test={test}\n```\n\nIt is also possible to use the [AliasAs](https://github.com/HelloKitty/TypeSafe.Http.Net/blob/master/src/TypeSafe.Http.Net.Metadata/Attributes/AliasAsAttribute.cs) Attribute to control the queryparameter name.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  Task Test([QueryStringParameter, AliasAs(\"param1\")] string test)\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test?param1={test}\n```\n\n### Request Body Content\n\nSometimes you want to send content in the request body. These are usually data models and it is possible to do this using the various body attributes. One major requirement is that the body content must be the first parameter in the method. See the examples below\n\n```csharp\npublic class TestModel\n{\n  //Sent\n  public string TestParameter { get; }\n  \n  //Sent\n  [AliasAs(\"Param2\")]\n  public string TestParameter2 { get; }\n  \n  //Not usually sent\n  private int Test3 { get; }\n}\n```\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  Task Test([UrlEncodedBody]TestModel model)\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test\nContent-Type: application/x-www-form-urlencoded\nBody: TestParameter={1}\u0026Param2={2}\n```\n\nIt is also possible to send just simple string content.\n\n```csharp\npublic interface IHttpServiceInterface\n{\n  [Get(\"/api/test\")]\n  Task Test([StringContent] string data)\n}\n```\n\nResult of calling Test:\n\n```\nGET {url}/api/test\nContent-Type: text/plain\nBody: {data}\n```\n\nThere are various other serializers that work in a similar fashion. Inlcude serializers like the [Json.NET Serializer Implementation](https://www.nuget.org/packages/TypeSafe.Http.Net.Serializer.JsonNET) and register it to use with [JsonBody](https://github.com/HelloKitty/TypeSafe.Http.Net/blob/master/src/TypeSafe.Http.Net.Metadata/Attributes/Serialization/Concrete/JsonBodyAttribute.cs) Attribute.\n\n### Response Body Content\n\nUnlike Refit the response content is deserialized based on the returned content-type. You do not need to annoate anything. This is handled internally. If a deserializer is not found that handles the returned content-type it will throw an exception.\n\nFor example if application/json is returned in the response body it will look for a register serializer that handles application/json and then try to deserialize it as a JSON object.\n\nThis design allows the internal library to handle deserialization for you based on how the server has returned the response. If you want to indicate a specific content type should be sent back use the HTTP recommended Accept headers.\n\n## Setup\n\nTo compile or open TypeSafe.Http.Net project you'll first need a couple of things:\n\n* Visual Studio 2017\n\n## Builds\n\nNuGet: [Core Library](https://www.nuget.org/packages/TypeSafe.Http.Net.Core/)\n\nNuGet: [.NET HttpClient Implementation](https://www.nuget.org/packages/TypeSafe.Http.Net.HttpClient/)\n\nNuGet: [Metadata/Attributes Library](https://www.nuget.org/packages/TypeSafe.Http.Net.Metadata/)\n\nNuGet: [JSON.Net (Newtonsoft) Serializer Implementation](https://www.nuget.org/packages/TypeSafe.Http.Net.Serializer.JsonNET/)\n\n\nMyget: [![hellokitty MyGet Build Status](https://www.myget.org/BuildSource/Badge/hellokitty?identifier=772ec112-a0e1-49b7-9d94-ede9ff28945a)](https://www.myget.org/)\n\n## Tests\n\nTODO actual tests\n\n|    | Linux Debug | Windows .NET Debug |\n|:---|----------------:|------------------:|\n|**master**| [![Build Status](https://travis-ci.org/HaloLive/HaloLive.Library.svg?branch=master)](https://travis-ci.org/HaloLive/HaloLive.Library)* | [![Build status](https://ci.appveyor.com/api/projects/status/rinvn2tdxn0yinf4?svg=true)](https://ci.appveyor.com/project/HelloKitty/halolive-library) |\n|**dev**| [![Build Status](https://travis-ci.org/HaloLive/HaloLive.Library.svg?branch=dev)](https://travis-ci.org/HaloLive/HaloLive.Library) | [![Build status](https://ci.appveyor.com/api/projects/status/rinvn2tdxn0yinf4/branch/dev?svg=true)](https://ci.appveyor.com/project/HelloKitty/halolive-library/branch/dev) |\n\n* Failing because TravisCI doesn't support net462 at the moment.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellokitty%2Ftypesafe.http.net","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhellokitty%2Ftypesafe.http.net","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellokitty%2Ftypesafe.http.net/lists"}