Модель MVC является нулевой в фильтре действий OnExecuted ... или более элегантным способом установки модели? - PullRequest
7 голосов
/ 27 мая 2011

У меня есть ActionFilter с переопределением для метода OnActionExecuted. FilterContext.Controller.ViewData.Model всегда имеет значение null для операции POST. Я нашел следующую статью, в которой, кажется, говорится, что она не должна быть нулевой, но, должно быть, это была более ранняя версия MVC. Это MVC3. Что я должен получить?

Наличие модели внутри ActionFilter

ОБНОВЛЕНИЕ:

Я разобрался с ответом на оригинальный вопрос. У меня был собственный ActionResult, который выводит JSON с пользовательским форматером даты. Проблема заключалась в том, что модель не устанавливается в контроллере.

В моем пользовательском ActionResult метод ExecuteResult передается ControllerContext, что было бы неплохо, если бы я мог установить там модель:

context.Controller.ViewData.Model = _data;

Но это в конце цикла, и результат в ActionFilter по-прежнему равен нулю. Кажется, это означает, что мне нужно вручную установить модель в контроллере:

ControllerContext.Controller.ViewData.Model = model; 

Или

View(model);

Что означает, что мне нужно помнить, чтобы делать это каждый раз, когда я использую этот собственный ActionResult. Есть ли более элегантный способ?

ЕЩЕ ДРУГОЕ ОБНОВЛЕНИЕ:

Я нашел способ сделать это, но он не так элегантен, как я надеялся.

В моем конструкторе для комода ActionResult, который я отправил в контроллер, таким образом, по крайней мере, он всегда будет согласован:

public JsonNetResult(object data, Controller controller) {
    SerializerSettings = new JsonSerializerSettings();
    _data = data;
    controller.ControllerContext.Controller.ViewData.Model = _data;
}

Ответы [ 2 ]

2 голосов
/ 26 июня 2012

Другой подход заключается в использовании базового контроллера для автоматической обработки сохранения набора параметров действий для последующего использования:

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Items["ActionParms"] = filterContext.ActionParameters.ToDictionary(p => p.Key, p => p.Value);
        base.OnActionExecuting(filterContext);
    }
}

, затем в вашем атрибуте:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var dictionary = filterContext.HttpContext.Items["ActionParms"] as Dictionary<string, object>;
    if (dictionary != null)
    {
        foreach (var o in dictionary.Keys)
        {
            // do something here
        }   
    }            
    base.OnActionExecuted(filterContext);
}

ИспользуетсяЭлементы HttpContext, которые не очень хороши, но я не знаю, что вы можете получить доступ к вашему ViewBag или ViewData в атрибуте.

Чтобы решить, хотите ли вы обрабатывать запрос в вашем атрибуте, вы можете опроситьимя действия и другая информация о параметрах:

var action = filterContext.ActionDescriptor.ActionName;
var parms = filterContext.ActionDescriptor.GetParameters();
foreach (var parameterDescriptor in parms)
{
    // do something here
}
1 голос
/ 11 августа 2014

Я нашел решение, подобное вашему, с помощью события OnModelUpdated, чтобы установить это свойство раньше.

У меня есть ModelBinder:

public class CustomModelBinder: DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        controllerContext.Controller.ViewData.Model = bindingContext.Model;
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

После этого вам нужно установить связыватель по умолчанию напривязка вашей новой модели в разделе Application_Start () в Global.asax:

ModelBinders.Binders.DefaultBinder = new CustomModelBinder ();

Наконец, вы можете получить доступ к вашей модели вActionFilter:

public class TraceLog : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //filterContext.Controller.ViewData.Model now isn't null
        base.OnActionExecuted(filterContext);
    }
}
...