Я начал идти по этому пути, а затем прочитал ваш ответ. Я объединил их в следующие файлы:
TempDataDictionaryExtensions.cs
Я создал методы расширения для грязной работы с TempData, потому что чувствовал, что он не принадлежит самому фильтру действий.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Project.Web.UI.Domain
{
public static class TempDataDictionaryExtensions
{
private const string _ModelStateErrorsKey = "ModelStateErrors";
public static IEnumerable<string> GetModelErrors(this TempDataDictionary instance)
{
return TempDataDictionaryExtensions.GetErrorsFromTempData(instance);
}
public static void AddModelError(this TempDataDictionary instance, string error)
{
TempDataDictionaryExtensions.AddModelErrors(instance, new List<string>() { error });
}
public static void AddModelErrors(this TempDataDictionary instance, IEnumerable<string> errors)
{
TempDataDictionaryExtensions.AddErrorsToTempData(instance, errors);
}
private static List<string> GetErrorsFromTempData(TempDataDictionary instance)
{
object tempObject = instance.FirstOrDefault(x => x.Key == TempDataDictionaryExtensions._ModelStateErrorsKey);
if (tempObject == null)
{
return new List<String>();
}
List<string> tempErrors = instance.FirstOrDefault(x => x.Key == TempDataDictionaryExtensions._ModelStateErrorsKey).Value as List<string>;
if (tempErrors == null)
{
return new List<String>();
}
return tempErrors;
}
private static void AddErrorsToTempData(TempDataDictionary instance, IEnumerable<string> errors)
{
List<string> tempErrors;
object tempObject = instance.FirstOrDefault(x => x.Key == TempDataDictionaryExtensions._ModelStateErrorsKey);
if (tempObject == null)
{
tempErrors = new List<String>();
}
else
{
tempErrors = instance.FirstOrDefault(x => x.Key == TempDataDictionaryExtensions._ModelStateErrorsKey).Value as List<string>;
if (tempErrors == null)
{
tempErrors = new List<String>();
}
}
tempErrors.AddRange(errors);
instance[TempDataDictionaryExtensions._ModelStateErrorsKey] = tempErrors;
}
}
}
TempDataModelStateAttribute.cs
Мой оригинал скопировал ошибки из TempData
обратно в ModelState
до выполнения ActionResult через OnResultExecuting
Это комбинация копирования их в TempData
и обратно.
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Project.Web.UI.Domain
{
public class TempDataModelStateAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
IEnumerable<string> modelErrors = ((Controller)filterContext.Controller).TempData.GetModelErrors();
if (modelErrors != null
&& modelErrors.Count() > 0)
{
modelErrors.ToList()
.ForEach(x => ((Controller)filterContext.Controller).ModelState.AddModelError("GenericError", x));
}
base.OnResultExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (!filterContext.Controller.ViewData.ModelState.IsValid)
{
if (filterContext.Result is RedirectResult
|| filterContext.Result is RedirectToRouteResult)
{
List<string> errors = new List<string>();
foreach (var obj in filterContext.Controller.ViewData.ModelState.Values)
{
foreach (var error in obj.Errors)
{
errors.Add(error.ErrorMessage);
}
}
((Controller)filterContext.Controller).TempData.AddModelErrors(errors);
}
}
base.OnActionExecuted(filterContext);
}
}
}