6

Ho un metodo per rimuovere l'oggetto. La rimozione non possiede la vista ed è un pulsante "Elimina" in "EditReport". Dopo aver rimosso con successo un reindirizzamento su "Report".Come continuare a utilizzare ModelState con RedirectToAction in ASP.NET MVC 6?

In ASP.NET MVC 5 Uso i seguenti attributi per salvare ModelState tra i metodi Ho preso da qui: 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"]); 
     } 
    } 
} 

Ma in ASP.NET MVC 6 RC 1 (ASP.NET core 1.0), questo codice non funziona.

Errore in filterContext.Controller non contiene definizioni per TempData e ViewData.

risposta

4

Grazie a answer, mi sono reso conto che la necessità di creare un codice 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); 
      } 
     } 
    } 
} 

Versione asincrona del codice ASP.NET Core 1.0 (.NET Framework completo 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

Ci dovrebbe essere un controllo per evitare che i non errori vengano visualizzati nella riga 'SetTempDataModelStateAttribute'' var listError = modelState.ToDictionary (m => m.Key, m => m.Value.Errors' dovrebbe essere 'modelState.Where (x => x.Value.Errors.Any()). ToDictionary (m ...' –

+1

Uso 'attendi dopo() ; 'non è corretto qui in quanto provoca il colpire quel metodo più volte. –

3

La correzione per compilare il codice è sotto, ma sembra che ASP.NET Core non supporti la serializzazione dello stato del modello (a causa di ModelStateEntry contenente eccezioni che non sono mai serializzabili).

Come tale, non è possibile serializzare lo stato del modello in TempData. E come spiegato in this GitHub issue, sembra che non ci siano piani per modificare questo comportamento.


La proprietà Controller in ActionExecutingContext è di tipo object. Questo perché i controllori in ASP.NET Core non sono obbligati ad ereditare da Controller, quindi non esiste un tipo di base comune per essi.

Per accedere alla proprietà TempData, è necessario prima convertirlo in Controller. I suoi attributi potrebbe apparire come questo allora:

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

Aggiungi al progetto Sessioni. Anche se non riesco a risolvere il problema con l'errore: 'InvalidOperationException: 'Microsoft.AspNet.Mvc.ViewFeatures.SessionStateTempDataProvider' non può serializzare un oggetto di tipo 'Microsoft.AspNet.Mvc.ModelBinding.ModelStateDictionary' allo stato di sessione'. –

+0

Sembra che ASP.NET Core non supporti la serializzazione dello stato del modello e non ci sono piani per cambiarlo. Ho aggiornato la mia risposta per riflettere questo. – poke

+0

correttamente convertirà ModelState in stringa (json) e memorizzerà in TempData? –