我正在try 创建一个自定义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);
    }
}

我知道我仍然需要判断空值等,但我不明白为什么grmemberGuid不能成功通过.我这样称呼这个过滤器:

    [CheckLoggedIn(gr = genesisRepository, memberGuid = md.memberGUID)]
    public ActionResult Home(MemberData md)
    {
        return View(md);
    }

控制器的构造函数中设置了genesisRepositorymd.

我无法编译这个.我得到的错误是:

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

我仔细判断了grmemberGuidgenesisReporitymd.memberGUID是同一类型,是什么导致了这些错误?

解决方案

感谢jfa提供了解决方案.

以下是我最终使用的过滤器:

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);
    }
}

推荐答案

这是实现这一目标的一种方式.您可以从ActionFilter对象访问ControllerContext,因此也可以访问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没有跨多个控制器使用,并且您可以接受耦合.另一种 Select 是使用共享属性创建一个ICheckedLoggedInController接口,然后简单地转换为该接口.

Asp.net相关问答推荐

是否可以发布 ASP.NET 5 应用程序以使目标机器不需要安装 DNX?

在 C# 中以编程方式添加元标记

测试项目中的 App.config

从 IIS 7/8 中的静态内容中删除服务器标头

在每个控制器的 ASP.NET WebAPI 上强制使用 CamelCase

在使用网络服务器加载它们之前,如何编译 Asp.Net Aspx 页面?

显示单选按钮列表内联

什么时候不应该使用 Web 服务?

如何在 ASP.NET 下拉列表中添加选项组?

Asp.net Identity 密码哈希

oAuth ASP.NET 成员资格提供程序

在asp.net控件之间动态添加

C# 7 本地函数未按预期工作且未显示错误

如何从 NuGet 安装 EntityFramework 5.0(和其他旧版本)?

Asp.Net web 服务:我想返回错误 403 禁止

C# - 将图像输出到响应输出流给出 GDI+ 错误

使用 Web.Config 转换的高级任务

判断 IQueryable 结果集的最佳方法是什么?

POST 字符串到 ASP.NET Web Api 应用程序 - 返回 null

如何在asp.net的GridView中按列名而不是按索引获取单元格值