7

OnActionExecuted メソッドをオーバーライドした ActionFilter があります。filterContext.Controller.ViewData.Model は、POST 操作では常に null です。null であってはならないと言っているように見える次の記事を見つけましたが、これは以前のバージョンの MVC であったに違いありません。これがMVC3です。私は何を得るべきですか?

ActionFilter 内のモデルの可用性

アップデート:

元の質問に対する答えを見つけました。カスタム日付フォーマッタで JSON を出力するカスタム ActionResult がありました。問題は、モデルがコントローラーに設定されていないことでした。

私のカスタム ActionResult では、ExecuteResult メソッドに ControllerContext が渡されます。ここで Model を設定できると便利です。

context.Controller.ViewData.Model = _data;

しかし、これはサイクルの後半であり、結果はActionFilterでまだnullです。これは、コントローラーにモデルを手動で設定する必要があることを意味しているようです。

ControllerContext.Controller.ViewData.Model = model; 

または

View(model);

つまり、このカスタム ActionResult を使用するたびに、これを行うことを忘れないでください。もっとエレガントな方法はありますか?

さらに別の更新:

これを行う方法を見つけましたが、思ったほどエレガントではありません。

コントローラーで送信するcomstom ActionResultのコンストラクターでは、少なくとも常に一貫性が保たれます。

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

2 に答える 2

2

もう 1 つの方法は、ベース コントローラーを使用して、後で使用するアクション パラメーター コレクションの格納を自動的に処理することです。

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
}
于 2012-06-26T14:29:34.593 に答える
1

OnModelUpdated イベントを使用してそのプロパティを設定する前に、あなたのようなソリューションを見つけました。

私は ModelBinder を持っています:

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

その後、Global.asax の Application_Start() セクションで、既定のバインダーを新しいモデル バインダーに設定する必要があります。

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);
    }
}
于 2014-08-11T18:43:32.877 に答える