How to keep using ModelState with RedirectToAction in ASP.NET MVC 6?

前端 未结 2 407
野性不改
野性不改 2021-01-05 14:14

I have a method to remove the object. Removal does not own view, and is a \"Delete\" button in the \"EditReport\". Upon successful removal of a redirect on \"Report\".

相关标签:
2条回答
  • 2021-01-05 14:36

    Thanks to answer, I realized that the need to create your own 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);
                }
            }
        }
    }
    

    Asynchronous version of the code ASP.NET Core 1.0 (Full .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();
            }
        }
    
    0 讨论(0)
  • 2021-01-05 14:47

    The fix to make the code compile is below, but it appears that ASP.NET Core does not support serializing the model state (due to ModelStateEntry containing exceptions which are never serializable).

    As such, you cannot serialize the model state in TempData. And as explained in this GitHub issue, there appear to be no plans to change this behavior.


    The Controller property in ActionExecutingContext is of type object. This is because controllers in ASP.NET Core are not required to inherit from Controller, so there is no common base type for them.

    In order to access the TempData property, you have to cast it to Controller first. Your attributes could look like this then:

    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 讨论(0)
提交回复
热议问题