WhatIsHeDoing.DomainModels

A library of domain models for .NET.


Keywords
domain, models, domain-driven-design, domain-model, dotnet, nuget-package, serialization
License
Unlicense
Install
Install-Package WhatIsHeDoing.DomainModels -Version 5.0.1

Documentation

WhatIsHeDoing.DomainModels

NuGet package NuGet downloads AppVeyor Windows build status Codecov code coverage Travis CI Linux build Status Codenvy workspace

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.

Web API

🦮 Usage

Installing

This package is available via NuGet, and targets .NET Core 2.2 for cross-platform use.

The Models

Barcodes

Locations

  • CountryCode: two and three-letter country codes.
  • UKPostcode: United Kingdom postcode

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 ▶️ feature; just click the dynamic preview URL it generates in the terminal.

Codenvy workspace

👱 Authors