web-dev-qa-db-ja.com

ActionFilter.OnActionExecuting()からApiControllerにオブジェクトを渡します

ActionFilter内のhttpリクエストごとにオブジェクトを作成し、このオブジェクトをコントローラーに渡したいと思います。これまで、次のようにRequest.Properties []を試しました。

public class DbReadonlyAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        actionContext.Request.Properties["CustomObjectKey"] = new MyClass();

また、新しいオブジェクトをControllerBaseクラスに直接割り当てようとしました。

public class DbReadonlyAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var controller = (MyControllerBase) actionContext.ControllerContext.Controller;
        controller.StorageContextFactory = new MyClass();

問題は、コントローラーメソッドが呼び出されるまでに新しいProperty ["CustomObjectKey"]がWebapiパイプラインで失われるため、どちらの手法もMyClassのインスタンスをコントローラーに配信しないことです。

コントローラーは、アクションフィルターOnActionExecuting()の呼び出し後に、webapiパイプラインによって再インスタンス化されます。

ブレークポイントは、Webapiパイプラインが単一のhttpリクエスト中に次のイベントフローをスケジュールすることを確認します。

  • コンストラクターMyControllerBase()
  • MyAuthenticationFilter
  • フィルターOnActionExecuting()
  • コンストラクターMyControllerBase()
  • MyController.MethodA()

MyControlerの二重インスタンス化は奇妙ですが、現在、新しく作成されたオブジェクトをアクションフィルターからコントローラーに渡す手法を探しています。

編集-1:この質問のv1で言及されているMyAuthorizationFilterは、実際には認証フィルターです。まだ調査中です。

解決策:バグは別のフィルターにありました。認証フィルターを削除した後、この質問で報告された問題はなくなりました。

14
camelCase

.addメソッドRequest.Propertiesコレクションを使用する必要があります。

public class DbReadonlyAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        actionContext.Request.Properties.Add(new KeyValuePair<string, object>("CustomObjectKey", new MyClass()));

この値は、APIコントローラーから取得できます。

object _customObject= null;

if (Request.Properties.TryGetValue("CustomObjectKey", out _customObjectKey))
{
    MyClass myObject = (MyClass)_customObject;
}
21
Sameer Azazi

ActionFilter.OnActionExecuting()からApiControllerに変数を渡す別の方法:

public class CustomFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        actionContext.ControllerContext.RequestContext.RouteData.Values["CustomValue"] = "CustomValue";
    }
}

Web API:にActionFilterAttributeを使用することに注意してください

System.Web.Http.Filters.ActionFilterAttribute

Not for MVC classic:

System.Web.Mvc.ActionFilterAttribute

使用:

[CustomFilter]
public class SomeController : ApiController
{
    string customValue = RequestContext.RouteData.Values.ToDictionary(x => x.Key, y => y.Value)["user_id"].ToString();
    //...
}
1
A. Morel