WhatIsHeDoing.DomainModels
A library of domain models for .NET.
👋 Introduction
As the Wikipedia article explains:
A domain model is a system of abstractions that describes select aspects of a sphere of knowledge, influence, or activity (a domain). The model can then be used to solve problems related to that domain. The domain model is a representation of meaningful real-world concepts pertinent to the domain that need to be modelled in software. The concepts include the data involved in the business and rules the business uses in relation to that data.
The domain models in this library implement a contract that ensures they are validated, serialised and deserialised, in a consistent manner.
Note: these models only validate their values, they do not verify them. That is, a model value
can be in the correct format, but it might not exist! You may still need to use another means to verify them,
such as calling a service. For example, the UK postcode SE1 9XX
is valid, but it does not exist.
📡 Demo
See how the Swagger demo site - use dotnet run --project WhatIsHeDoing.DomainModels.APITest
-
handles URL, JSON and XML domain model de/serialisation.
🦮 Usage
Installing
This package is available via NuGet, and targets .NET Core 2.2 for cross-platform use.
The Models
Barcodes
Locations
An Example
Let's say you are capturing the address of user in the United Kingdom in a web form, and posting it
to a .NET Web API. The postcode is a mix of alphanumeric characters, often separated by a space, so
why not simply use a string
?
public class Address
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Town { get; set; }
public string Country { get; set; }
public string Postcode { get; set; }
}
The Problems
Whilst a postcode looks simple enough, it is comprised of multiple different components, and is validated by a
surprisingly complex regular expression. If it is stored as a string
, when is it validated, and where does
that logic reside? If it is passed to a Web API, you could add a model annotation, but what about other scenarios,
such as console and mobile apps? What happens when we need to access only parts of that postcode, such as
the postcode area, which could be used to determine whether the user is based in Northern Ireland?
Using a Domain Model
Capturing the same information in a domain model is as simple as switching to the UKPostcode
type:
public class Address
{
// As before, but now:
public UKPostcode Postcode { get; set; }
}
Now, when the data is passed to the service, we can check the ModelState
as usual, before moving on:
namespace Test
{
using Microsoft.AspNetCore.Mvc;
using Models;
using System.Net;
using WhatIsHeDoing.DomainModels.Locations;
[Route("api/[controller]")]
public class UserDetailsController : Controller
{
/// <summary>
/// Does something useful with an address.
/// </summary>
/// <param name="address">Address to use</param>
/// <returns>Success</returns>
[HttpPost]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public IActionResult Post(Address address) => ModelState.IsValid
? Ok(address.Postcode.PostcodeArea)
: (ActionResult)new BadRequestResult();
}
}
This works for both JSON (using Json.NET) and XML serialisation.
The underlying Value
type is a string
, and the model provides an implicit string operator override,
as you can see from unit tests like this from the WhatIsHeDoing.DomainModels.Test
project:
[Fact]
public void StringFormat()
{
var postcode = new UKPostcode("SW1 1AA");
var actual = $"Hello from {postcode}!";
Assert.Equal("Hello from SW1 1AA!", actual);
}
🆘 Contributing
All contributions are greatly welcomed! Please see the contributing guide for more information.
If you are developing locally, pull down this repo and build within Visual Studio (any edition), or
run dotnet test
on any platform; the master
branch is continuously built on both Windows
and Linux. Alternatively, simply create a new Codenvy workspace from my factory!
You can even run the API test project by simply using the Run
preview
URL it generates in the terminal.
👱 Authors
- Darren Hickling: https://darrenhickling.com/