コントローラーから渡される一連のパラメーターを操作するカスタムActionFilterを作成しようとしています。
これまでのところ、私の顧客ActionFilterは次のようになります。
public class CheckLoggedIn : ActionFilterAttribute
{
public IGenesisRepository gr { get; set; }
public Guid memberGuid { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Member thisMember = gr.GetActiveMember(memberGuid);
Member bottomMember = gr.GetMemberOnBottom();
if (thisMember.Role.Tier <= bottomMember.Role.Tier)
{
filterContext
.HttpContext
.Response
.RedirectToRoute(new { controller = "Member", action = "Login" });
}
base.OnActionExecuting(filterContext);
}
}
ヌルなどをまだチェックする必要があることはわかっていますが、gr
とmemberGuid
が正常に渡されない理由を理解できません。私はこのフィルターを次のように呼んでいます:
[CheckLoggedIn(gr = genesisRepository, memberGuid = md.memberGUID)]
public ActionResult Home(MemberData md)
{
return View(md);
}
genesisRepository
とmd
は、コントローラーのコンストラクターで設定されています。
これをコンパイルすることはできません。私が得るエラーは:
Error 1 'gr' is not a valid named attribute argument because it is not a valid attribute parameter type
Error 2 'memberGuid' is not a valid named attribute argument because it is not a valid attribute parameter type
gr
およびmemberGuid
がgenesisRepority
およびmd.memberGUID
と同じタイプであることを再確認しました。これらのエラーの原因は何ですか?
ソリューションを提供してくれたjfarに感謝します。
使用したフィルターは次のとおりです。
public class CheckLoggedIn : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var thisController = ((MemberController)filterContext.Controller);
IGenesisRepository gr = thisController.GenesisRepository;
Guid memberGuid = ((MemberData)filterContext.HttpContext.Session[thisController.MemberKey]).MemberGUID;
Member thisMember = gr.GetActiveMember(memberGuid);
Member bottomMember = gr.GetMemberOnBottom();
if (thisMember.Role.Tier >= bottomMember.Role.Tier)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new {
controller = "Member",
action = "Login"
}));
}
base.OnActionExecuting(filterContext);
}
}
これは、この機能を実現する方法です。 ControllerFilterにアクセスできるため、ActionFilterオブジェクトからControllerにアクセスできます。あなたがする必要があるのは、コントローラをその型にキャストするだけで、あなたはパブリックメンバーにアクセスできます。
このコントローラーが与えられた場合:
public GenesisController : Controller
{
[CheckLoggedIn()]
public ActionResult Home(MemberData md)
{
return View(md);
}
}
ActionFilterは次のようになります
public class CheckLoggedIn : ActionFilterAttribute
{
public IGenesisRepository gr { get; set; }
public Guid memberGuid { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
/* how to get the controller*/
var controllerUsingThisAttribute = ((GenesisController)filterContext.Controller);
/* now you can use the public properties from the controller */
gr = controllerUsingThisAttribute .genesisRepository;
memberGuid = (controllerUsingThisAttribute .memberGuid;
Member thisMember = gr.GetActiveMember(memberGuid);
Member bottomMember = gr.GetMemberOnBottom();
if (thisMember.Role.Tier <= bottomMember.Role.Tier)
{
filterContext
.HttpContext
.Response
.RedirectToRoute(new { controller = "Member", action = "Login" });
}
base.OnActionExecuting(filterContext);
}
}
もちろん、これはActionFilterが複数のコントローラーで使用されておらず、カップリングで問題ないことを前提としています。別のオプションは、共有プロパティでICheckedLoggedInControllerインターフェイスを作成し、代わりに単純にキャストすることです。
属性プロパティには定数値のみを使用できます。完全な説明については、 このページ を参照してください。
属性は、本質的に型に追加されるメタデータです。インスタンス変数の代わりに、const
値のみを使用できます。あなたの場合、あなたはgenisisRepository
などのインスタンス変数を渡そうとしています。これらはコンパイル時定数ではないため、コンパイルに失敗します。
これを実現するには、通常はIoCコンテナーを使用して、アクションフィルターの依存性注入を調べる必要があります。
また、ActionFilterがOnActionExecuted
などのPostActionResultアクションを実行している場合、おそらくルートデータに何かを保存することで回避できます。
public ActionResult Index()
{
ControllerContext.RouteData.DataTokens.Add("name", "value");
return View();
}