{"id":24125783,"url":"https://github.com/binarymash/responses","last_synced_at":"2025-09-18T17:31:07.498Z","repository":{"id":144199251,"uuid":"76105905","full_name":"binarymash/responses","owner":"binarymash","description":null,"archived":false,"fork":false,"pushed_at":"2017-05-16T17:17:06.000Z","size":77,"stargazers_count":1,"open_issues_count":3,"forks_count":2,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-08-27T13:37:17.103Z","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/binarymash.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-10T10:32:36.000Z","updated_at":"2017-03-11T09:05:10.000Z","dependencies_parsed_at":"2023-06-16T14:00:30.842Z","dependency_job_id":null,"html_url":"https://github.com/binarymash/responses","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/binarymash/responses","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarymash%2Fresponses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarymash%2Fresponses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarymash%2Fresponses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarymash%2Fresponses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/binarymash","download_url":"https://codeload.github.com/binarymash/responses/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarymash%2Fresponses/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275804591,"owners_count":25531711,"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","status":"online","status_checked_at":"2025-09-18T02:00:09.552Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-01-11T15:37:25.677Z","updated_at":"2025-09-18T17:31:07.491Z","avatar_url":"https://github.com/binarymash.png","language":"C#","readme":"# Responses\n\n[![license](https://img.shields.io/github/license/binarymash/responses.svg)](https://github.com/binarymash/responses/blob/develop/LICENSE) [![NuGet version](https://badge.fury.io/nu/binarymash.responses.svg)](https://badge.fury.io/nu/binarymash.responses) [![Build status](https://ci.appveyor.com/api/projects/status/p51dvusrw32u9b17/branch/develop?svg=true)](https://ci.appveyor.com/project/binarymash/responses/branch/develop) [![Coverage Status](https://coveralls.io/repos/github/binarymash/responses/badge.svg?branch=master)](https://coveralls.io/github/binarymash/responses?branch=master)\n\n## Introduction\n\nThis library provides a fluent API for building standardized response objects that, optionally, contain payloads and errors.\n\nBuilt in .NET Core and targetting [.NET Standard 1.1](https://github.com/dotnet/standard/blob/master/docs/versions.md), the library can be used in .NET Framework \u003e= 4.5, or cross-platform in .NET Core \u003e= 1.0.\n\n### Example\n\nLets assume our existing code defines an `Address` object:\n\n```csharp\nclass Address\n{\n\tpublic Name { get; set; }\n\tpublic Street { get; set; }\n\tpublic City { get; set; }\n\t// etc...\n}\n\nvar address = new Address(...) // initialise values\n```\n\nWe can use `BuildResponse` to build a `Response` that contains an `Address` instance, and set an `Error` on the response...\n\n```csharp\nvar response = BuildResponse\n    .WithPayload(address)\n    .AndWithErrors(new Error(\"InvalidName\", \"The name must be set\"))\n    .Create();\n```\n\n...and then the response serialized to JSON is...\n\n```json\n{\n\t\"Payload\":\n    {\n\t\t\"Name\":\"\",\n        \"Street\":\"Buckingham Palace\",\n        \"City\":\"London\"\n    },\n    \"Errors\":[\n    \t{ \"Code\":\"InvalidName\", \"Message\":\"The name must be set\" }\n    ]\n}\n```\n\n## Installing\n\n[![NuGet version](https://badge.fury.io/nu/binarymash.responses.svg)](https://badge.fury.io/nu/binarymash.responses)\n\nStable builds are published to [Nuget](https://www.nuget.org/packages/BinaryMash.Responses/). The package name is `BinaryMash.Responses`\n\n## How to use\n\nYou'll find everything you need in the `Binarymash.Responses` namespace.\n\n```csharp\nusing BinaryMash.Responses;\n```\n\n### Response types\nThere are two types of response object; the type of response to use will depend on what we want it to contain.\n\n`BinaryMash.Responses.Response\u003cT\u003e` is a response that contains a strongly typed payload. We will use this when we want to return a value from a method:\n\n```csharp\n// synchronous example\nResponse\u003cAddress\u003e GetAddress(uint id); // replaces Address GetAddress(uint id)\n\n// asynchronous example\nasync Task\u003cResponse\u003cAddress\u003e\u003e GetAddress(uint id); // replaces async Task\u003cAddress\u003e GetAddress(unit id)\n```\n\n`BinaryMash.Responses.Response` is a response that contains no payload. We will use this when we don't care about a return value:\n\n```csharp\n// synchronous example\nResponse SetAddress(); // replaces void SetAddress(Address address)\n\n// asynchronous example\nasync Task\u003cResponse\u003e SetAddress(Address address); // replaces async Task SetAddress(Address address)\n```\n\n\nNow, lets look at how to create these responses.\n\n### Empty response\n\nThe simplest example creates an empty response:\n\n```csharp\nvar response = BuildResponse\n    .WithNoPayload()\n    .Create();\n```\n\n...serialzed into JSON, this response will look like...\n\n```json\n{\n\t\"Errors\":[]\n}\n```\n\nNotice that the empty response contains an empty collection of errors. Lets learn how to add some errors to a response.\n\n### Empty response with errors\n\nThe following code lets us add errors to the empty response.\n\n```csharp\nvar response = BuildResponse\n    .WithNoPayload()\n    // errors can be added individually...\n    .AndWithErrors(new Error(\"InvalidName\", \"The name must be set\"))\n    // ...and as a collection...\n    .AndWithErrors(new []\n    {\n        new Error(\"InvalidStreet\", \"The street must be set\"),\n        new Error(\"InvalidCity\", \"The city must be set\")\n    })\n    .Create();\n```\n\nSerialized, this looks like...\n\n```json\n{\n\t\"Errors\":[\n    \t{ \"Code\":\"InvalidName\", \"Message\":\"The name must be set\" },\n        { \"Code\":\"InvalidStreet\", \"Message\":\"The street must be set\" },\n        { \"Code\":\"InvalidCity\", \"Message\":\"The city must be set\" }\n     ]\n}\n```\n\nGreat. We can create a response with errors. But how do we include a payload value?\n\n### Payload response\n\nLets assume we have an address object...\n\n```csharp\nclass Address\n{\n\tpublic Name { get; set; }\n\tpublic Street { get; set; }\n\tpublic City { get; set; }\n\t// etc...\n}\n```\n\nThis code builds a response that contains an instance of `Address`.\n\n```csharp\nAddress address;\n\n// some code here to set value of address (not shown)\n\nvar response = BuildResponse\n    .WithPayload\u003cAddress\u003e(address)\n    .Create();\n```\n\nIn most cases the compiler will infer the type of the payload from the value you supply, so we can omit the type definition from the code.\n\n```csharp\n\t// ...\n    .WithPayload(address)\n\t// ...\n```\n\nThe serialized response is...\n\n```json\n{\n\t\"Payload\":\n    {\n\t\t\"Name\":\"The Queen of England\",\n        \"Street\":\"Buckingham Palace\",\n        \"City\":\"London\"\n    },\n    \"Errors\":[]\n}\n```\n\n### Payload response with errors\n\nOf course, we can add errors to the payload response in just the same way we did on the empty response:\n\n```csharp\nvar response = BuildResponse\n    .WithPayload(address)\n    .AndWithErrors(new Error(\"InvalidName\", \"The name must be set\"))\n    .Create();\n```\n\n### Payload response with default value\n\nIf we are setting errors on a payload response, we might decide it is not meaningful to also set a value in the payload. However, will likely be constrained at compile time to return a `Response\u003cT\u003e` rather than a `Response`.\n\nIn this case, rather than having to always explicitly specify a value for the payload, we can choose to implicitly return the default value of our payload type. We can do this by using the parameterless version of `.WithPayload\u003cT\u003e()`...\n\n```csharp\nvar response = BuildResponse\n    .WithPayload\u003cAddress\u003e()\n    .AndWithErrors(new Error(\"InvalidName\", \"The name must be set\"))\n    .Create();\n```\n\nThis is exactly the same as explicitly setting the default value:\n\n```csharp\n    // ...\n    .WithPayload\u003cAddress\u003e(default(Address))\n    // ...\n```\n\nIn most cases it will be the same as setting the payload to null:\n\n```csharp\n\t// ...\n    .WithPayload((Address)null)\n    // ...\n```\n\nThe serialized output will look something like this:\n\n```json\n{\n\t\"Payload\":null,\n    \"Errors\":[\n    \t{\"Code\":\"InvalidName\",\"Message\":\"The name must be set\"}\n    ]\n}\n```\n\n### Runtime Activation\nIn some cases it might not be possible to know at compile time the exact type of response you want to create without using reflection. In the example below, we don't know at compile time if `TResponse` is a payload-less `Response` or if it is a `Response\u003cTPayload\u003e`. Even if it does have a payload, we can't be sure of its type.\n\nIn this situation, we cannot easily use `.WithNoPayload()` or `.WithPayload\u003cTPayload\u003e()`. However, the library provides another method to create a response: `.WithType\u003cTResponse\u003e()`. \n\n\n```csharp\npublic TResponse Handle(TRequest request)\n{\n    // The code that calls this method specifies exactly what type TResponse is.\n\n    var response = BuildResponse\n        .WithType\u003cTResponse\u003e()\n        .AndWithPayload(new Address()) // dangerous! Do we know for sure that the TResponse has a payload of this type?\n        .AndWithErrors(new Error(\"InvalidName\", \"The name must be set\"))\n        .Create();\n\n    return response;\n}\n```\n\nNote that this mechanism is not as strongly typed as the other methods; you will get exceptions at runtime if you try to use mismatching types. So, you should only use this option if you really have no alternative.\n\n## Build Status\n\nThe repository is built on [AppVeyor](https://ci.appveyor.com/project/binarymash/responses).\n\n### Stable\n\n[![Build status](https://ci.appveyor.com/api/projects/status/p51dvusrw32u9b17/branch/master?svg=true)](https://ci.appveyor.com/project/binarymash/responses/branch/master)\n\n[![Coverage Status](https://coveralls.io/repos/github/binarymash/responses/badge.svg?branch=master)](https://coveralls.io/github/binarymash/responses?branch=master)\n\n### Development\n\n\n[![Build status](https://ci.appveyor.com/api/projects/status/p51dvusrw32u9b17/branch/develop?svg=true)](https://ci.appveyor.com/project/binarymash/responses/branch/develop)\n\n[![Coverage Status](https://coveralls.io/repos/github/binarymash/responses/badge.svg?branch=develop)](https://coveralls.io/github/binarymash/responses?branch=develop)\n\nDevelopment builds are published to https://www.myget.org/F/binarymash-unstable/api/v3/index.json\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinarymash%2Fresponses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinarymash%2Fresponses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinarymash%2Fresponses/lists"}