0

我有控制器的操作,它與一些實體(驅動程序)一起工作。此外,每個驅動程序鏈接與身份配置文件如何在許多控制器的許多操作中實現一些代碼

 public async Task<ActionResult> Details(int? id) 
     { 
      if ((id == null)) 
      { 
       return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
      } 
      DriverDetailVM model = mapper.Map<DriverDetailVM>(db.Drivers.Find(id)); 
      if ((model == null)) 
      { 
       return HttpNotFound(); 
      } 
      return View(model); 
     } 

     public async Task<ActionResult> Edit(int? id = null, bool isNewUser = false) 
     { 
///////// 
     } 

如果用戶有角色「超級管理員」然後,他訪問具有價值的任何標識的頁面。如果用戶具有「驅動程序」角色,那麼只有當id值與他的個人資料相同時,我們才應該有權訪問。我嘗試實現它ActionFilter:

public class DriverAccessActionFilterAttribute : ActionFilterAttribute 
{ 
    public string IdParamName { get; set; } 
    public int DriverID { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (filterContext.HttpContext.User.IsInRole("Driver")) 
     { 
      if (filterContext.ActionParameters.ContainsKey(IdParamName)) 
      { 
       var id = filterContext.ActionParameters[IdParamName] as Int32; 
       if (id != DriverID) 
        filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); 
      } 
      else 
       filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 
     else 
      base.OnActionExecuting(filterContext); 
    } 
} 

但是當我嘗試使用此代碼:

[DriverAccessActionFilter(DriverID = currentUser.DriverId, IdParamName = "id")] 
    public async Task<ActionResult> Details(int? id) 
    { 

它不希望被編譯,因爲

對象引用所需的非靜電場,方法或 屬性

如何實現它?

回答

2

屬性參數在編譯時評估,而不是在運行時評估。所以他們必須是編譯時間常量。您無法在運行時將值傳遞給動作屬性。即在[DriverAccessActionFilter(DriverID = currentUser.DriverId, IdParamName = "id")]您通過DriverID = currentUser.DriverId。一個屬性用作控制器/操作元數據,元數據需要在彙編中編譯。這就是爲什麼屬性只能取值不變的原因。

你必須改變你的屬性如下:

  1. 使用依賴注入注入你的服務,回報用戶登錄。
  2. 或實現自定義委託人併爲其分配當前請求委託人。

您可以通過修改屬性作爲跟隨的情況下,要實現CustomPrinicpal:

public class DriverAccessActionFilterAttribute : ActionFilterAttribute 
    { 
     public string IdParamName { get; set; } 
     private int DriverID { get; set; } 

     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     {    
      if (filterContext.HttpContext.User.IsInRole("Driver")) 
      { 
       var customPrincipal = filterContext.HttpContext.User as CustomPrincipal; 
       DriverID = customPrincipal.Id; 
       // Rest of you logic     
      } 
      else 
       base.OnActionExecuting(filterContext); 
     } 
    } 

如果您選擇DI路徑,那麼你可以使用下面的代碼片段:

public class DriverAccessActionFilterAttribute : ActionFilterAttribute 
{ 
    public string IdParamName { get; set; } 
    private int DriverID { get; set; } 

    public DriverAccessActionFilterAttribute(IYourIdentityProvider provider) 
    { 
     DriverID = provider.LoggedInUserID; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    {    
     // Your logic 
    } 
} 

,然後用你的屬性爲[DriverAccessActionFilter(IdParamName = "id")]

+0

我想過校長,謝謝 –

+0

不客氣,試着開車'AuthorizationFilterAttribute'而不是'ActionFilterAttribute'。 – Zeeshan