我正在开发一个ASP.NET WebForms项目,我们需要能够根据当前用户的“组”在整个应用程序中配置行为。这适用于应用程序的几乎所有方面,包括站点导航,在页面上显示/隐藏某些用户控件,以及在某些情况下执行自定义业务逻辑。但是,绝大多数应用程序行为都是在组之间共享的,因此我们排除了创建完全独立的应用程序的想法。
基本上,我正在寻找的是在ASP.NET WebForms应用程序中实现自定义行为的架构方法。有没有比在视图层,业务层和持久层中的代码库中使用if / else语句更好的方法?
修改:一些例子:
如果是A组中的用户,他们的 导航将包含所有 从B组导航加上一些 其他链接。
如果用户在A组中,则会有一个页面 显示用户控件c1,c2和c3。 如果用户在B组,他们会 只能在同一页面上看到c1和c3。
如果用户在表单上保存了一些数据 他们在A组,发送一个 通知邮箱。如果是用户 在B组中,发送短信 代替。
我们可以解决所有这些特定问题,但正在寻找一种尽可能多地封装此行为的方法,因此它不会分散在代码库中。
编辑:有一些与动态加载用户控件相关的有趣答案。是否应该根据用户的组确定要加载哪些控件或使用哪种行为的逻辑被封装在一个(非内聚)类中,例如:
GroupManager.GetNavigationControl(int groupId) // loads site nav control based on group
GroupManager.PerformNotification(int groupId) // sends text or email based on group
或者这个逻辑是否应该尽可能接近使用它的代码中的位置,因此应该分布在代码库的不同层中?
答案 0 :(得分:1)
“群组”是指“角色”吗?如果你在谈论角色,你可以通过做这样的事情来设置你的行为
If User.IsInRole("SomeRandomRole") Then
'Do some random behavioral crap
ElseIF User.IsInRole("TheCoolRole") Then
'Do some cool behavioral crap
Else
'Do generic crap
End If
另一种选择可能是基于角色使用UserControls。因此,当您加载页面时,它将根据请求它的角色加载用户控件。
你可以让一个PlaceHolder坐空,并从代码隐藏中调用LoadControl方法。
然后,您的所有用户控件都将匹配您的角色
角色=管理员| UserControl = Admin.ascx
角色=用户| UserControl = User.ascx
答案 1 :(得分:1)
这里没有吨详细信息,但我怀疑你可能会受益于多态(即各种接口实现)来处理用户组之间不同的应用程序部分。像Spring.NET这样的Inversion of Control容器可以帮助您根据当前用户角色将这些不同的实现连接起来/配置在一起。您也可以从Spring的面向方面编程API中受益,您可以在其中装饰业务层/数据访问层中的方法,以便可以执行授权逻辑。
答案 2 :(得分:1)
没有详细介绍IoC等等,我认为我会保持它非常简单并且有一个普通的旧工厂类,你可以使用它返回适当的实例化UI元素[用户控件]基于当前用户发出请求。在这样做时,您将在一个位置拥有所有“if”语句。要使用'if'语句,您只需创建一个映射配置文件或DB表,其中包含对用户属于特定组时要使用的用户控件的引用。
注意:这两个选项都会导致在页面上创建动态控件,这并非没有自身的复杂性,但我已经成功地在我的应用程序中使用动态控件而没有问题一段时间了 - 这只是一个问题对于页面生命周期的沮丧和肮脏,比我最初感觉舒服。
答案 3 :(得分:0)
您也可以继承Principal对象来处理这个问题。
以下是我在具有以下自定义规则的应用程序中的完成方式:
创建了我自己的IPrincipal对象,该对象来自我的“Person”对象,以便能够继承查找组和角色等的能力:
public class Principal : MyNamespace.Person, IPrincipal {
}
使当前上下文使用我的IPrincipal对象:
protected void Application_AuthenticateRequest(Object Sender, EventArgs E) {
if (HttpContext.Current.User != null &&
HttpContext.Current.User.Identity.IsAuthenticated &&
HttpContext.Current.User.Identity is FormsIdentity) {
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
HttpContext.Current.User = new MyNamespace.Principal(id);
}
}
然后我制作了静态方法,这样每次我想让当前用户都不需要这样做:
public class CurrentUser {
/// <summary>
/// Is the current user authenticated
/// </summary>
static public bool IsAuthed {
get { return System.Web.HttpContext.Current.User.Identity.IsAuthenticated; }
}
/// <summary>
/// Returns the Principal object in case it is needed. Also used for other static properties of this class.
/// </summary>
static public MyNamespace.Principal User {
get {
return (MyNamespace.Principal)System.Web.HttpContext.Current.User;
}
}
}
然后你可以调用像CurrentUser.User.IsInGroup()这样的东西。