Prevent certain fields from being overwritten with PATCH in .NET Azure Web Api
I am creating an Azure Mobile Service with a .NET backend that uses TableController (a 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 AccountController, where I do not want to field Username
and UserId
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'd like to send a response HTTP request like 403: Forbidden
or similar if the client connecting to the API tries to update the username or userId. So I need some way to either find out the contents of the Delta patch, or get an autoresponder when "forbidden" fields are updated.
source to share
Not sure if there is a built-in way to do this. However, you can work around this. Create a new attribute, say NonEditable
.
public class NonEditableAttribute: Attribute
{
}
Apply this attribute to properties that you do not want to fix.
public class Account
{
[NonEditable]
public string UserName {get;set;}
... other properties
}
Write some helper method that checks if changed properties Delta<T>
do not contain 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 it contains Delta<T>
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: The code is untested and could be better designed. This should give you a general idea - treat it as pseudocode.
source to share