C# 防止.NET Azure Web Api中的修补程序覆盖某些字段

C# 防止.NET Azure Web Api中的修补程序覆盖某些字段,c#,.net,azure,asp.net-web-api,C#,.net,Azure,Asp.net Web Api,我正在创建一个带有.NET后端的Azure移动服务,它使用TableController(ApicController的子类)来处理REST请求 在我的补丁方法中,我想限制允许更新的字段集。我有一个AccountController,我不想覆盖Username和UserId字段 public class AccountController : TableController<Account> { ... // PATCH tables/TodoItem/48D68C86-6EA6-4

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

在我的补丁方法中,我想限制允许更新的字段集。我有一个AccountController,我不想覆盖
Username
UserId
字段

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);          
   }
...
}
公共类AccountController:TableController
{
...
//修补表/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
公共任务修补程序帐户(字符串id,增量修补程序)
{            
返回UpdateSync(id,补丁);
}
...
}

如果连接到API的客户机试图更新用户名或用户ID,我想返回一个有意义的HTTP响应,如
403:probled
或类似的响应。因此,我需要知道增量补丁的内容,或者在更新“禁止”字段时自动响应。

不确定是否有内置的方法。但是,您可以解决这个问题。创建新属性,比如说
不可编辑

public class NonEditableAttribute: Attribute 
{
}
将此属性应用于不希望修补的属性

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

   ... other properties
}
编写一些助手方法,检查
Delta
上更改的属性是否包含这些不可编辑的属性

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;
}
public bool IsValidDelta(Delta-Delta),其中T:class
{
//无法修补的属性名称列表
var nonEditablePropertyNames=来自typeof(T).GetProperties()中的p
设attr=p.GetCustomAttribute(typeof(NonEditableAttribute))
其中attr!=null
选择p.名称;
//已更改的属性名称列表
var changedPropertyNames=delta.GetChangedPropertyNames();
//检查ChangedPropertyName是否包含任何PropertyName,
//如果是,返回false,如果否,返回true;
}
现在,在ApiController中,只需检查
Delta
是否包含不可编辑的已更改属性

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...
   }
...
}
公共类AccountController:TableController
{
...
//修补表/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
公共任务修补程序帐户(字符串id,增量修补程序)
{    
if(IsValidDelta(补丁))
返回UpdateSync(id,补丁);
其他的
//禁止。。。
}
...
}

请注意:代码未经测试,可以进行更好的设计。这是给你一个大概的想法——把它当作伪代码。

这太棒了,Michael!!谢谢主要的一点当然是在调用
UpdateAsync
方法作为响应之前运行您自己的验证逻辑。我通常会发现,在许多类似这样的实现中,条件更多地基于授权逻辑或基于被修补资源状态的逻辑,但这在模型定义中使用了数据注释属性。