Prevent certain fields from being overwritten with PATCH in .NET Azure Web Api

.net, asp.net-web-api, azure, c#

Solution

Not sure if there is a built-in way to do that. However, you can workaround this. Create new attribute, let's say `NonEditable`.

public class NonEditableAttribute: Attribute 
{
}

Apply this attribute to properties you don't want to be patched.

public class Account
{
   [NonEditable]
   public string UserName {get;set;}

   ... other properties
}

Write some helper method that will check if changed properties on `Delta<T>` contains any of these non editable properties.

public bool IsValidDelta<T>(Delta<T> delta) where T: class
{
   // list of property names that can't be patched
   var nonEditablePropertyNames = from p in typeof(T).GetProperties()
                    let attr = p.GetCustomAttribute(typeof(NonEditableAttribute))
                    where attr != null
                    select p.Name;
   // list of property names that were changed
   var changedPropertyNames = delta.GetChangedPropertyNames();

   // check if changedPropertyNames contains any of propertyNames, 
   // if yes return false, if no return true;
}

Now, in your ApiController, just check if `Delta<T>` contains changed properties, that are not editable

public class AccountController : TableController<Account>
{
...
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
   public Task<Account> PatchAccount(string id, Delta<Account> patch)
   {    
       if(IsValidDelta(patch))        
            return UpdateAsync(id, patch);          
       else
          // forbidden...
   }
...
}

Please Note: Code is not tested, and can be better designed. This is to give you general idea - treat it as pseudo code.

Problem

I am creating an Azure Mobile Service with a .NET backend which uses a TableController (subclass of ApiController) to handle REST requests. In my PATCH method I want to restrict the set of fields that are allowed to be updated. I have an AccountController where I don't want the fields `Username` and `UserId` to be overwritten. ``` public class AccountController : TableController<Account> { ... // PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959 public Task<Account> PatchAccount(string id, Delta<Account> patch) { return UpdateAsync(id, patch); } ... } ``` I would like to send back a meaningful HTTP response like `403: Forbidden` or similar if a client connecting to the API tries to update the username or userId. So I need some way of either knowing the content of the Delta patch or having an auto response when the 'forbidden' fields are being updated.

Original source