6

Ich habe eine Methode, um das Objekt zu entfernen. Die Entfernung besitzt keine eigene Ansicht und ist eine Schaltfläche "Löschen" im "EditReport". Nach erfolgreichem Entfernen einer Weiterleitung auf "Report".Wie Verwenden von ModelState mit RedirectToAction in ASP.NET MVC 6?

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

In ASP.NET MVC 5 verwende ich die folgenden Attribute, um ModelState zwischen Methoden zu speichern. Ich nahm von hier: https://stackoverflow.com/a/12024227/3878213

public class SetTempDataModelStateAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     base.OnActionExecuted(filterContext);   
     filterContext.Controller.TempData["ModelState"] = 
      filterContext.Controller.ViewData.ModelState; 
    } 
} 

public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 
     if (filterContext.Controller.TempData.ContainsKey("ModelState")) 
     { 
      filterContext.Controller.ViewData.ModelState.Merge(
       (ModelStateDictionary)filterContext.Controller.TempData["ModelState"]); 
     } 
    } 
} 

Aber in ASP.NET MVC 6 RC 1 (ASP.NET-Core 1.0), dieser Code funktioniert nicht.

Fehler in filterContext.Controller enthält keine Definitionen für TempData und ViewData.

Antwort

4

Dank answer, erkannte ich, dass die Notwendigkeit, Ihren eigenen Code ASP.NET-Core 1.0 (Full .NET Framework 4.6.2)

public class SetTempDataModelStateAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     base.OnActionExecuted(filterContext); 

     var controller = filterContext.Controller as Controller; 
     var modelState = controller?.ViewData.ModelState; 
     if (modelState != null) 
     { 
      var listError = modelState.Where(x => x.Value.Errors.Any()) 
       .ToDictionary(m => m.Key, m => m.Value.Errors 
       .Select(s => s.ErrorMessage) 
       .FirstOrDefault(s => s != null)); 
      controller.TempData["ModelState"] = JsonConvert.SerializeObject(listError); 
     } 
    } 
} 
public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     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 = 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); 
      } 
     } 
    } 
} 

zu erstellen Asynchrone Version des Codes ASP.NET Core 1.0 (Vollständiges .NET Framework 4.6.2)

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.Where(x => x.Value.Errors.Any()) 
        .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(); 
     } 
    } 
+1

Es sollte eine Prüfung zu verhindern, dass keine Fehler in 'SetTempDataModelStateAttribute' line' var listError = modelState.ToDictionary (m => m.Key, m => m.Value.Errors sollte "modelState.Where (x => x.Value.Errors.Any()) sein. ToDictionary (m ...' –

+1

Mit 'aware next() ; 'ist hier falsch, da dadurch die Methode mehrfach getroffen wird. –

3

Das Update, um den Code zu kompilieren, ist unten, aber es scheint, dass ASP.NET Core Serialisierung des Modellstatus nicht unterstützt (aufgrund ModelStateEntry enthält Ausnahmen, die nie serialisierbar sind).

Daher kann der Modellstatus in TempData nicht serialisiert werden. Und wie in this GitHub issue erläutert, scheint es keine Pläne zu geben, dieses Verhalten zu ändern.


Die Controller Eigenschaft in ActionExecutingContext ist vom Typ object. Dies liegt daran, dass Controller in ASP.NET Core nicht von Controller erben müssen. Daher gibt es keinen gemeinsamen Basistyp für sie.

Um auf die TempData-Eigenschaft zugreifen zu können, müssen Sie sie zunächst auf Controller umwandeln. Ihre Attribute wie diese dann aussehen könnte:

public class SetTempDataModelStateAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     base.OnActionExecuted(filterContext); 

     Controller controller = filterContext.Controller as Controller; 
     if (controller != null) 
     { 
      controller.TempData["ModelState"] = controller.ViewData.ModelState; 
     } 
    } 
} 

public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     Controller controller = filterContext.Controller as Controller; 
     if (controller != null & controller.TempData.ContainsKey("ModelState")) 
     { 
      controller.ViewData.ModelState.Merge(
       (ModelStateDictionary)controller.TempData["ModelState"]); 
     } 
    } 
} 
+0

Zum Projekt hinzufügen. Während ich das Problem mit dem Fehler nicht lösen kann: 'InvalidOperationException: Der 'Microsoft.AspNet.Mvc.ViewFeatures.SessionStateTempDataProvider' kann ein Objekt vom Typ 'Microsoft.AspNet.Mvc.ModelBinding.ModelStateDictionary' nicht in den Sitzungszustand serialisieren. –

+0

Es scheint, dass ASP.NET Core das Serialisieren des Modellstatus nicht unterstützt, und es gibt keine Pläne, das zu ändern. Ich habe meine Antwort aktualisiert, um das zu reflektieren. – poke

+0

ordnungsgemäß wird ModelState in Zeichenfolge (JSON) konvertieren und in TempData speichern? –

Verwandte Themen