Search code examples
restservicestackormlite-servicestack

Is this a good pattern for PATCH


I am implementing a REST style API that allows an object to be PATCH'ed. The intention of the PATCH operation is to allow one or more properties in a class to be updated without touching an of the other properties that may be set.

The are examples of partial updates on the ServiceStack OrmLite page, but it seems to need hardcoding to indicate which fields will be partially updated. In my scenario it is upto the depend application to decide which fields to send.

I also have to cope with the scenario that the object may not have been persisted yet.

To get around this I have implemented the following:

public object Patch(Myclass request)
{
    HttpStatusCode SuccessCode;
    try
    {
        var result = (MyClass)Get(request);
        if (result != null)
        {
            request.PopulateWithNonDefaultValues(result);
            dbFactory.Run(dbCmd => dbCmd.UpdateNonDefaults(request, r => r.myId == request.myId));
        }
        else
        {
            dbFactory.Run(dbCmd => dbCmd.Save(request));
        }

        SuccessCode = HttpStatusCode.Accepted;
    }
    catch (Exception e)
    {
        log.Error(e);
        SuccessCode = HttpStatusCode.InternalServerError;
    }
    return new HttpResult()
    {
        StatusCode = SuccessCode
    };
}

It works, but something doesn't feel right, I'm sure there must be a better way?


Solution

  • That looks ok although you're code will be a lot shorter if you just throw let it throw C# Exceptions when there's an error and if you're inheriting from ServiceStack's New API base Service class you can use the already available Db property, e.g:

    public object Patch(Myclass request)
    {
    
        var result = (MyClass)Get(request);
        if (result != null)
        {
            request.PopulateWithNonDefaultValues(result);
            Db.UpdateNonDefaults(request, r => r.myId == request.myId);
        }
        else
        {
            Db.Save(request);
        }
    
        return new HttpResult
        {
            StatusCode = HttpStatusCode.Accepted
        };
    }