2

我有一個方法來刪除對象。刪除不擁有自己的視圖,並且是「EditReport」中的「刪除」按鈕。成功刪除「報告」後的重定向。在ASP.NET Core 1.0中使用ModelState和RedirectToAction的異步

[HttpPost] 
[Route("{reportId:int}")] 
[ValidateAntiForgeryToken] 
public async Task<IActionResult> DeleteReport(int reportId) 
{ 
    var success = await _reportService.DeleteReportControlAsync(reportId); 
    if (success == false) 
    { 
     ModelState.AddModelError("Error", "Messages"); 
     return RedirectToAction("EditReport"); 
    } 
    ModelState.AddModelError("OK", "Messages"); 
    return RedirectToAction("Report"); 
} 

在ASP.NET Core 1.0(完全.NET Framework)中,我使用以下屬性在方法之間保存ModelState。我從這裏拿走了:https://stackoverflow.com/a/35987804/3878213

我最近轉向使用控制器,服務和存儲庫的異步方法。 在我看來,行動的屬性也應該是異步的。 起初,我重寫了代碼屬性如下:

public class SetTempDataModelStateAttribute : Attribute, IAsyncActionFilter 
    { 
     public async Task OnActionExecutionAsync(ActionExecutingContext filterContext, ActionExecutionDelegate next) 
     {  
      var controller = filterContext.Controller as Controller; 
      var modelState = controller?.ViewData.ModelState; 
      if (modelState != null) 
      { 
       var listError = modelState.ToDictionary(m => m.Key, m => m.Value.Errors 
        .Select(s => s.ErrorMessage) 
        .FirstOrDefault(s => s != null)); 
       var listErrorJson = await Task.Run(() => JsonConvert.SerializeObject(listError)); 
       controller.TempData["ModelState"] = listErrorJson; 
      } 
      await next(); 
     } 
    } 
public class RestoreModelStateFromTempDataAttribute : Attribute, IAsyncActionFilter 
{ 
    public async Task OnActionExecutionAsync(ActionExecutingContext filterContext, ActionExecutionDelegate next) 
    { 
     var controller = filterContext.Controller as Controller; 
     var tempData = controller?.TempData?.Keys; 
     if (controller != null && tempData != null) 
     { 
      if (tempData.Contains("ModelState")) 
      { 
       var modelStateString = controller.TempData["ModelState"].ToString(); 
       var listError = await Task.Run(() => 
        JsonConvert.DeserializeObject<Dictionary<string, string>>(modelStateString)); 
       var modelState = new ModelStateDictionary(); 
       foreach (var item in listError) 
       { 
        modelState.AddModelError(item.Key, item.Value ?? ""); 
       } 

       controller.ViewData.ModelState.Merge(modelState); 
      } 
     } 
     await next(); 
    } 
} 

似乎合乎邏輯給我。但是這個代碼並不像我預期的那樣工作。 但是,下面的異步屬性都正常工作:

public class SetTempDataModelStateAttribute : ActionFilterAttribute 
    { 
     public override async Task OnActionExecutionAsync(ActionExecutingContext filterContext, ActionExecutionDelegate next) 
     { 
      await base.OnActionExecutionAsync(filterContext, next); 

      var controller = filterContext.Controller as Controller; 
      var modelState = controller?.ViewData.ModelState; 
      if (modelState != null) 
      { 
       var listError = modelState.ToDictionary(m => m.Key, m => m.Value.Errors 
        .Select(s => s.ErrorMessage) 
        .FirstOrDefault(s => s != null)); 
       var listErrorJson = await Task.Run(() => JsonConvert.SerializeObject(listError)); 
       controller.TempData["ModelState"] = listErrorJson; 
      } 
      await next(); 
     } 
    } 
public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute 
    { 
     public override async Task OnActionExecutionAsync(ActionExecutingContext filterContext, ActionExecutionDelegate next) 
     { 
      await base.OnActionExecutionAsync(filterContext, next); 

      var controller = filterContext.Controller as Controller; 
      var tempData = controller?.TempData?.Keys; 
      if (controller != null && tempData != null) 
      { 
       if (tempData.Contains("ModelState")) 
       { 
        var modelStateString = controller.TempData["ModelState"].ToString(); 
        var listError = await Task.Run(() => 
         JsonConvert.DeserializeObject<Dictionary<string, string>>(modelStateString)); 
        var modelState = new ModelStateDictionary(); 
        foreach (var item in listError) 
        { 
         modelState.AddModelError(item.Key, item.Value ?? ""); 
        } 

        controller.ViewData.ModelState.Merge(modelState); 
       } 
      } 
      await next(); 
     } 
    } 

請告訴我這兩個選項更正確?爲什麼沒有工作的第一個選項?

+0

使用'await next();'在這裏不正確,因爲它導致該方法被多次命中。 –

回答

2

請告訴我哪兩個選項更正確。

選項二更爲正確,因爲它實際上可行 - 正如您已經注意到的那樣。如果你不打算繼承它,他們可能已經做到了sealed。在這種情況下使用ActionFilterAttribute似乎是適當的。事實上,一個quick look @ the repo顯示這實際上是一個非常普遍的方法。

爲什麼第一個選項不起作用?

它不調用base調用。關鍵是base調用中可能存在您在自定義實現中缺少的代碼。檢查出來here

相關問題