I have a requrement to provide an api which would allow to change status of  Order. Api is supposed to follow REST principles, so I have designed an endpoint like this:/api/orders/{orderId}/statusDecision to expose separate resource of status rather than including it into order resource as a property was driven by necessity of displaying audit fields for status - timestamp and changedby.The Order workflow includes a lot of transitions between statuses. So far controller+resource model:public class OrderStatusController : ApiController{    private readonly IOrderStatusApiService _apiService;    public OrderStatusController(IOrderStatusApiService apiService)    {        _apiService = apiService;    }    public OrderStatusModel Get(int orderId)    {        return _apiService.Get(orderId);    }    public OrderStatusModel Put(int orderId, [FromBody]OrderStatusModel orderStatus)    {        return _apiService.Update(orderId, orderStatus);    }}public class OrderStatusModel{    public string Note { get; set; }    public OrderStatusEnum Status { get; set; }    public DateTime TimeStamp { get; set; }    public string ChangedBy { get; set; }}public enum OrderStatusEnum{    Requested = 1,    Processing = 2,    //... others    Done = 99}The usage example:User B calls GET. Response is { status: Requested, timestamp: 2017-08-20T05:53:45Z, ChangedBy: User A }User B PUTs { status: Processing, note: it's time to start }. Response is (for future GET too) { status: Processing, timestamp: 2017-08-20T05:54:45Z, ChangedBy: User B }.The next layer is ApiServices:public interface IOrderStatusApiService{    OrderStatusModel Get(int orderId);    OrderStatusModel Update(int orderId, OrderStatusModel orderStatus);}public class OrderStatusApiService : IOrderStatusApiService{    private readonly IOrderStatusAppService _appService;    public OrderStatusApiService(IOrderStatusAppService appService)    {        _appService = appService;    }    public OrderStatusModel Get(int orderId)    {        return _appService.Get(orderId).ToResourceModel();    }    public OrderStatusModel Update(int orderId, OrderStatusModel order)    {        var currentState = _appService.Get(orderId).ToResourceModel();        if (currentState.Status != order.Status)        {            return _appService                .UpdateStatus(orderId, (OrderStatusEnumDto)order.Status, order.Note)                .ToResourceModel();        }        return currentState;    }}AppService here is responsible for dealing with business domain objects, I'd like to skip details of its implementation for now. Just worth mentioning the interface - its signature includes primitive types and dtos in order to decouple API and domain levels. The definition is provided below. Also I've decided to make a check whether current state of the resource is different from what user have passed. To my mind ApiService may operate with resource state and decide whether AppService layer should be called or not. For example transfer from Processing to Processing state doesn't make sense from business perspective (business domain should throw an exception in such a case, shouldn't it?), but why two subsequent PUTs with the same body should fail?  public interface IOrderStatusAppService{    OrderStatusDto Get(int orderId);    OrderStatusDto UpdateStatus(int orderId, OrderStatusEnum orderStatusStatus, string orderStatusNote);}To make mapping between Dto-ResourceModel look fluent, extension methods were implemented:public static class OrderStatusExtensions{    public static OrderStatusModel ToResourceModel(this OrderStatusDto dto)    {        return new OrderStatusModel()                   {                       ChangedBy = dto.ChangedBy,                       Note = dto.Note,                       Status = dto.Status,                       TimeStamp = dto.TimeStamp                   };    }}The Dto layer now looks like a copy of resource model, however I feel like it is not a big price for decoupling:public class OrderStatusDto{    public string Note { get; set; }    public OrderStatusEnumDto Status { get; set; }    public DateTime TimeStamp { get; set; }    public string ChangedBy { get; set; }}public enum OrderStatusEnumDto{    Requested = 1,    Processing = 2,    //... others    Done = 99}
Rest Api design to handle status migrations
.net;rest;asp.net web api