防止某些字段被.NET Azure Web Api中的PATCH覆盖

Dan*_*iel 6 .net c# azure asp.net-web-api

我正在创建一个具有.NET后端的Azure移动服务,该后端使用TableController(ApiController的子类)来处理REST请求。

在我的PATCH方法中,我想限制允许更新的字段集。我有一个AccountController,我不想在其中将字段UsernameUserId覆盖。

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);          
   }
...
}
Run Code Online (Sandbox Code Playgroud)

403: Forbidden如果连接到API的客户端尝试更新用户名或userId,我想发送有意义或类似的HTTP响应。因此,我需要某种方式来了解Delta补丁的内容,或者在更新“禁止”字段时具有自动响应。

Mic*_*ael 5

不确定是否有内置的方法来做到这一点。但是,您可以解决此问题。创建新属性,比方说NonEditable

public class NonEditableAttribute: Attribute 
{
}
Run Code Online (Sandbox Code Playgroud)

将此属性应用于您不想修补的属性。

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

   ... other properties
}
Run Code Online (Sandbox Code Playgroud)

编写一些辅助方法来检查更改的属性是否Delta<T>包含任何这些不可编辑的属性。

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;
}
Run Code Online (Sandbox Code Playgroud)

现在,在您的 ApiController 中,只需检查是否Delta<T>包含不可编辑的已更改属性

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...
   }
...
}
Run Code Online (Sandbox Code Playgroud)

请注意:代码未经测试,可以更好地设计。这是为了给你一个大致的想法 - 把它当作伪代码。