https://github.com/binarymash/responses
https://github.com/binarymash/responses
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/binarymash/responses
- Owner: binarymash
- License: mit
- Created: 2016-12-10T10:32:36.000Z (about 9 years ago)
- Default Branch: develop
- Last Pushed: 2017-05-16T17:17:06.000Z (almost 9 years ago)
- Last Synced: 2025-08-27T13:37:17.103Z (6 months ago)
- Language: C#
- Size: 75.2 KB
- Stars: 1
- Watchers: 3
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Responses
[](https://github.com/binarymash/responses/blob/develop/LICENSE) [](https://badge.fury.io/nu/binarymash.responses) [](https://ci.appveyor.com/project/binarymash/responses/branch/develop) [](https://coveralls.io/github/binarymash/responses?branch=master)
## Introduction
This library provides a fluent API for building standardized response objects that, optionally, contain payloads and errors.
Built 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 >= 4.5, or cross-platform in .NET Core >= 1.0.
### Example
Lets assume our existing code defines an `Address` object:
```csharp
class Address
{
public Name { get; set; }
public Street { get; set; }
public City { get; set; }
// etc...
}
var address = new Address(...) // initialise values
```
We can use `BuildResponse` to build a `Response` that contains an `Address` instance, and set an `Error` on the response...
```csharp
var response = BuildResponse
.WithPayload(address)
.AndWithErrors(new Error("InvalidName", "The name must be set"))
.Create();
```
...and then the response serialized to JSON is...
```json
{
"Payload":
{
"Name":"",
"Street":"Buckingham Palace",
"City":"London"
},
"Errors":[
{ "Code":"InvalidName", "Message":"The name must be set" }
]
}
```
## Installing
[](https://badge.fury.io/nu/binarymash.responses)
Stable builds are published to [Nuget](https://www.nuget.org/packages/BinaryMash.Responses/). The package name is `BinaryMash.Responses`
## How to use
You'll find everything you need in the `Binarymash.Responses` namespace.
```csharp
using BinaryMash.Responses;
```
### Response types
There are two types of response object; the type of response to use will depend on what we want it to contain.
`BinaryMash.Responses.Response` is a response that contains a strongly typed payload. We will use this when we want to return a value from a method:
```csharp
// synchronous example
Response
GetAddress(uint id); // replaces Address GetAddress(uint id)
// asynchronous example
async Task> GetAddress(uint id); // replaces async Task
GetAddress(unit id)
```
`BinaryMash.Responses.Response` is a response that contains no payload. We will use this when we don't care about a return value:
```csharp
// synchronous example
Response SetAddress(); // replaces void SetAddress(Address address)
// asynchronous example
async Task SetAddress(Address address); // replaces async Task SetAddress(Address address)
```
Now, lets look at how to create these responses.
### Empty response
The simplest example creates an empty response:
```csharp
var response = BuildResponse
.WithNoPayload()
.Create();
```
...serialzed into JSON, this response will look like...
```json
{
"Errors":[]
}
```
Notice that the empty response contains an empty collection of errors. Lets learn how to add some errors to a response.
### Empty response with errors
The following code lets us add errors to the empty response.
```csharp
var response = BuildResponse
.WithNoPayload()
// errors can be added individually...
.AndWithErrors(new Error("InvalidName", "The name must be set"))
// ...and as a collection...
.AndWithErrors(new []
{
new Error("InvalidStreet", "The street must be set"),
new Error("InvalidCity", "The city must be set")
})
.Create();
```
Serialized, this looks like...
```json
{
"Errors":[
{ "Code":"InvalidName", "Message":"The name must be set" },
{ "Code":"InvalidStreet", "Message":"The street must be set" },
{ "Code":"InvalidCity", "Message":"The city must be set" }
]
}
```
Great. We can create a response with errors. But how do we include a payload value?
### Payload response
Lets assume we have an address object...
```csharp
class Address
{
public Name { get; set; }
public Street { get; set; }
public City { get; set; }
// etc...
}
```
This code builds a response that contains an instance of `Address`.
```csharp
Address address;
// some code here to set value of address (not shown)
var response = BuildResponse
.WithPayload
(address)
.Create();
```
In 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.
```csharp
// ...
.WithPayload(address)
// ...
```
The serialized response is...
```json
{
"Payload":
{
"Name":"The Queen of England",
"Street":"Buckingham Palace",
"City":"London"
},
"Errors":[]
}
```
### Payload response with errors
Of course, we can add errors to the payload response in just the same way we did on the empty response:
```csharp
var response = BuildResponse
.WithPayload(address)
.AndWithErrors(new Error("InvalidName", "The name must be set"))
.Create();
```
### Payload response with default value
If 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` rather than a `Response`.
In 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()`...
```csharp
var response = BuildResponse
.WithPayload
()
.AndWithErrors(new Error("InvalidName", "The name must be set"))
.Create();
```
This is exactly the same as explicitly setting the default value:
```csharp
// ...
.WithPayload
(default(Address))
// ...
```
In most cases it will be the same as setting the payload to null:
```csharp
// ...
.WithPayload((Address)null)
// ...
```
The serialized output will look something like this:
```json
{
"Payload":null,
"Errors":[
{"Code":"InvalidName","Message":"The name must be set"}
]
}
```
### Runtime Activation
In 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`. Even if it does have a payload, we can't be sure of its type.
In this situation, we cannot easily use `.WithNoPayload()` or `.WithPayload()`. However, the library provides another method to create a response: `.WithType()`.
```csharp
public TResponse Handle(TRequest request)
{
// The code that calls this method specifies exactly what type TResponse is.
var response = BuildResponse
.WithType()
.AndWithPayload(new Address()) // dangerous! Do we know for sure that the TResponse has a payload of this type?
.AndWithErrors(new Error("InvalidName", "The name must be set"))
.Create();
return response;
}
```
Note 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.
## Build Status
The repository is built on [AppVeyor](https://ci.appveyor.com/project/binarymash/responses).
### Stable
[](https://ci.appveyor.com/project/binarymash/responses/branch/master)
[](https://coveralls.io/github/binarymash/responses?branch=master)
### Development
[](https://ci.appveyor.com/project/binarymash/responses/branch/develop)
[](https://coveralls.io/github/binarymash/responses?branch=develop)
Development builds are published to https://www.myget.org/F/binarymash-unstable/api/v3/index.json