艾伟:[一步一步MVC]第一回:使用ActionSelector控制Action的选择

本系列文章导航

[一步一步MVC]第一回:使用ActionSelector控制Action的选择

[一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理

[一步一步MVC]第三回:MVC范例大观园

[一步一步MVC]第四回:漫谈ActionLink,有时“胡搅蛮缠”

[一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper

[一步一步MVC]第六回:什么是MVC(上)?

ActionFilter一定是MVC控制中对于Action控制中最值得研究的玩意,在项目实际中我们不可避免的使用例如:

  • HandleError
  • Authorized
  • OutputCache

在本文中,我们应用Action Selector方式进行Action的选择,想要阐述清楚这个问题,我们从实际的问题出发来关注。

实际的问题,从和老赵的对话了解

我们有个业务室这样的:系统有不同的角色,例如Admin、Client、Agent。假设有个功能叫Book/List,那么就对应了一个List这样的View和action为List这样的BookController,现在,我们的情况是对于不同的角色,所对应的List是不同的。Admin看到的Book/List和Client看到的Book/List是不同的,那么通过Url:http://anytao.com/Book/List/123,不同的角色如何处理,差不多就这样,是否清楚。

:那么对于同一Action如何更好的return到不同的view?

老赵:具体问题是什么呢?

: 我现在能想到的是在Action中根据角色Return到不同的View,简单的办法就是在List Action根据角色Return到不同的View。问题是,还有什么更好的办法。

老赵:准备n各action,分别加上自定的ActionSelector,不要用一个Action,不用一个Action然后在里面if。

[OnlyInRole("admin")] [ActionName("List")]ListForAdmin() {}

[OnlyInRole("user")] [ActionName("List")]ListForUser() {}

OnlyInRole需要自己写,不过就几行话

: 哈哈,差不多了,谢啦。

根据老赵的指导,我对此思路进行了必要的探讨,感受果然不同凡响,很好很暴力。

解决方案

为了实现对于Action进行Selector的具体实现,我选择对ActionNameSelectorAttribute 进行扩展,参考ActionName的实现方式,对于按照RoleType进行过滤的需求显然有很好的借鉴价值,以ActionNameAttribute为例,其具体实现为:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]public sealed class ActionNameAttribute : ActionNameSelectorAttribute {

public ActionNameAttribute(string name) {if (String.IsNullOrEmpty(name)) {throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");        }

Name = name;    }

public string Name {get;private set;    }

public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) {return String.Equals(actionName, Name, StringComparison.OrdinalIgnoreCase);    }

}

再来了解ActionNameSelectorAttribute抽象类的定义,其主要提供了对Action进行Select时的IsValidName判断约定,例如ActionNameSelectorAttribute的定义:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]public abstract class ActionNameSelectorAttribute : Attribute {public abstract bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo);}

所以,对ActionNameSelecterAttribute进行扩展变得异常简单,下面是一个最简单的实现,肯定让我们耳目一新:

// Release : code01, 2009/04/17                    // Author  : Anytao, http://www.anytao.compublic class ActionInRoleAttribute : ActionNameSelectorAttribute{public ActionInRoleAttribute(RoleType role)    {this.role = role;    }

public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)    {if (controllerContext.HttpContext.User.IsInRole(role.ToString()))        {return true;        }else        {return false;        }    }

private RoleType role;}

我们的逻辑其实很简单,借助于IPrincipal的IsInRole方法,可以很简单的根据role的定义进行IsValidName过滤,例如我们的应该可以就是:

// Release : code02, 2009/04/17                    // Author  : Anytao, http://www.anytao.com[AcceptVerbs(HttpVerbs.Get)][ActionName("List")][ActionInRole(RoleType.Client)]public ActionResult ClientList(int id){return View("ClientBookList",new Book        {            ID = id,            Name = string.Empty        });}

// Release : code03, 2009/04/17                    // Author  : Anytao, http://www.anytao.com[AcceptVerbs(HttpVerbs.Get)][ActionName("List")][ActionInRole(RoleType.Admin)]public ActionResult AdminList(int id){return View("AdminBookList",new Book        {            ID = id,            Name = string.Empty        });}

调用List Action时,根据登陆用户的角色来决定具体执行的Action(ClientList或者AdminList),并由不同的Action导航到不同的View(ClientBookList或者AdminBookList),而对于不同Action访问的URL都是一样的(http://anytao.com/Book/List/123),同时避免了在服务层对角色的判断,某种程度上按照RoleType对于Controller层进行了“注入”,使得Controller层的逻辑不在关心Action过滤的问题。

不过,在应用上还有一些值得注意的问题:

  • 使用非泛型ActionLink方法调用应用ActionInRole 的Action

一般而言,我们提倡应用强类型ModelData在View层进行操作,那么泛型方法ActionLink值得推荐,

<p><%= Html.ActionLink<BookController>(c => c.List(Model.ID), "List") %></p>

然而,应用被ActionInRole标记的,同时被ActionName重命名的Action,将不被识别,我们只好以非泛型方式实现对于一名多用的Action来调用:

<p><%= Html.ActionLink("List", "List", new { id=Model.ID }) %></p>
  • 在return View中通过制定ViewName进行返回,来选择适合的View,例如
return View("AdminBookList",new Book    {        ID = id,        Name = string.Empty    });

因为默认情况下,MVC引擎是以ActionName进行返回的,在我们的应用中必须以这种方式进行。

结论

本文着重于应用,而没有特别对什么是ActionFilter进行探讨,我们在合适的时间再次与MVC握手,对此进行进一步进行讨论。

时间: 2024-07-31 13:06:41

艾伟:[一步一步MVC]第一回:使用ActionSelector控制Action的选择的相关文章

[一步一步MVC]第一回:使用ActionSelector控制Action的选择

ActionFilter一定是MVC控制中对于Action控制中最值得研究的玩意,在项目实际中我们不可避免的使用例如: HandleError Authorized OutputCache 在本文中,我们应用Action Selector方式进行Action的选择,想要阐述清楚这个问题,我们从实际的问题出发来关注. 实际的问题,从和老赵的对话了解 我们有个业务室这样的:系统有不同的角色,例如Admin.Client.Agent.假设有个功能叫Book/List,那么就对应了一个List这样的Vi

艾伟_转载:[一步一步MVC]第六回:什么是MVC(上)?

本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [一步一步MVC]第三回:MVC范例大观园 [一步一步MVC]第四回:漫谈ActionLink,有时"胡搅蛮缠" [一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper [一步一步MVC]第六回:什么是MVC(上)? 引言 所谓MVC,其实就是M.V.C而已.归根揭底,

艾伟_转载:[一步一步MVC]第四回:漫谈ActionLink,有时“胡搅蛮缠”

本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [一步一步MVC]第三回:MVC范例大观园 [一步一步MVC]第四回:漫谈ActionLink,有时"胡搅蛮缠" [一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper [一步一步MVC]第六回:什么是MVC(上)? MVC时代来临了,但是一开始是不被很多人接受的.可能

艾伟_转载:[一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper

本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [一步一步MVC]第三回:MVC范例大观园 [一步一步MVC]第四回:漫谈ActionLink,有时"胡搅蛮缠" [一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper [一步一步MVC]第六回:什么是MVC(上)? 对HtmlHelper进行扩展,是MVC中对于Vie

艾伟_转载:[一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理

本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [一步一步MVC]第三回:MVC范例大观园 [一步一步MVC]第四回:漫谈ActionLink,有时"胡搅蛮缠" [一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper [一步一步MVC]第六回:什么是MVC(上)? 由问题引出 在ASP .NET MVC中,以友好的U

[一步一步MVC]第六回:什么是MVC(上)?

本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [一步一步MVC]第三回:MVC范例大观园 [一步一步MVC]第四回:漫谈ActionLink,有时"胡搅蛮缠" [一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper [一步一步MVC]第六回:什么是MVC(上)? 引言 所谓MVC,其实就是M.V.C而已.归根揭底,

艾伟_转载:学习 ASP.NET MVC (第一回)理论篇

本系列文章导航 学习 ASP.NET MVC (第一回)理论篇 学习 ASP.NET MVC (第二回)实战篇 学习 ASP.NET MVC (第三回)实战篇 学习 ASP.NET MVC (第四回)实战篇 学习 ASP.NET MVC (第五回)理论篇 MVC三种角色:--Model:用于存储数据的组件--View:根据Model数据进行内容展示的组件--Controller:接受并处理用户指令(操作Model),选择一个View并输出内容.Controller对View进行引用,但是View

一步一步写算法(之 回数)

原文:一步一步写算法(之 回数) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     回数的概念比较好玩,就是说有这么一个字符串str, 长度为n, 现在index开始从0->index/2遍历,那么str[index] = str[n-1-index],那么这种数据就是我们通常说的回数.比如说a = "a"是回数, a = "aba"是回数, a = "strarts"也是回数

一步一步封装自己的HtmlHelper组件BootstrapHelper(三)_javascript技巧

前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. BootstrapHelper系列文章目录 C#进阶系列--一步一步封装自己的HtmlHelper组件:BootstrapHelper C#进阶系列--一步一步封装自己的HtmlHelper组件:BootstrapHelper(二) C#进阶系列--一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码) 一.Nu