会员+管理系统,第一部分:引导

注意:本系列的每一篇文章都可以为数据服务提供不同的数据模式。由于历史原因,它们位于不同的源代码控制分支上。因此,前面的文章可能不会与后面的文章同步。在其他文章中尝试重用数据服务和样例数据时应该小心。 相关文章 为ASP. net会员商店提供基于服务的会员提供者。网络会员+管理系统,第二部分:账号设置+管理系统,第三部分:查询智能 内容1。介绍2。背景3。成员资格+数据模式4。设置解决方案4.1数据服务相关项目Net membership API 4.3 membership +应用层和测试4.4创建和更新web应用程序4.5添加无bootstrap源nuget包4.6自定义bootstrap 4.6.1修改变量。更少的文件4.6.2创建网站。4.7.1顶部导航条4.7.2改变登录和注册视图4.8“Hello world!”5. 设置数据Service5.1编译文档6。连接到数据服务6.1设置机器密钥6.2配置WCF为客户端6.3配置成员存储6.4选择一个示例数据源6.5再次运行6.5.1尝试演示6.5.2重新启动7。初始化成员数据7.1使用数据服务操作安装7.1.1前端数据库级别7.1.2数据集级别7.2添加根和根用户7.2.1添加根角色7.2.2根角色分配给根用户7.3添加各种类型7.3.1 UserGroupTypes 7.3.2其他类型7.3.3提醒8。历史1。介绍^这是系列文章的第一篇的设计、初始化和实现一个叫做会员+扩展会员系统,提供在线会员管理、成员互动,各种各样的成员目录,高级会员查询、会员沟通,和社交网络等功能。本文描述了数据模式和建立开发环境的过程,后续文章将提供实现的详细信息。对于那些需要为自己的web开发项目设置这样一个环境的读者来说,它也很有价值。我们选择了一种基于服务和数据库无关的架构。系统使用了一些最新的稳定框架,包括Asp。Net Mvc, WCF, HTML5+CSS3, LESS, jQuery, jQuery UI, knockoutjs, bootstrap等。许多组织,如公司、政府机构、教育机构、俱乐部、互联网服务提供商、各种协会等,都需要对会员进行在线管理和协调。目前的系统是在前几篇文章“ASP的基于服务的会员提供者”中发布的系统的扩展。NET"发布在这里和"会员商店为ASP。它没有实现特定应用程序逻辑的用户和角色管理界面。当然,数据服务的web接口可用于在安全环境中查询和/或操作与成员资格相关的数据。但当一个人开始考虑它,他/她可能意识到这样的管理设置有局限性。这是因为组织中只有少数值得信任的技术人员(比如DBA)可以管理成员,其他进行实际人力资源管理的管理人员必须“手动”将任务委派给上述少数成员。如果一个组织的规模变得很大(比如超过100人),就需要一个等级分明的管理结构,在这个结构中,成员有序地分担责任。在处理成员之间的关系时,情况会变得更加微妙。例如,如果一个组织的管理结构的演变是由一组共享一个子集职责的当前管理人员保护的,那么如何允许系统在没有太多人工干预的情况下支持正确的基于规则的角色分配过程呢?很明显,角色有不同的重要性;角色不应该由角色不那么重要的成员分配给任何人,否则系统将不稳定。此外,具有共同角色的一组成员在与同一角色组的其他成员打交道时也应该有一定的差异,以便他们在寻求外部帮助之前尽可能地按照既定的规则进行,在行动上没有冲突这个系统。然而,上一篇文章中介绍的角色系统过于简单,无法支持这样的系统。会员系统应该至少几种成员目录,以便成员可以根据多个方案用于各种目的,如缓解成员发现,代表组织结构,代表项目归属,控制传播的信息(在公告、消息、邮件清单等)。除了这种静态分类系统,会员系统还应该允许成员搜索或过滤。它应该接近底层数据服务对应的智能结构化查询能力的质量。会员系统还应该支持会员关系管理,从简单的联系人列表到更复杂的社交图圈导航。它应该有一个基于组的公告和个人事件安排系统,可以由组中的成员共享,或者由特定社交圈中与所有者相关的成员共享。所有这些活动都应该可以在会员数据服务的安全环境之外的internet上进行。为了简化引导程序,系统的当前版本中没有包含重要的部分,即对成员通信的本地支持。会员+系统由四大层组成:数据服务。以分布式和数据库无关的方式,将成员相关的关系数据抽象并封装到一个公共数据服务中,需要操作或使用上述数据的各种应用程序可以调用该服务。该数据服务包含完整的API用于查询,查询智能和操纵成员相关数据的客户端能够与WCF服务通信,它包括所有的。net框架,javascripts和其他有WCF适配器的系统。这里提供的数据服务是一个准备使用的软件包。数据服务的客户端的应用程序,执行特定的应用程序逻辑、视图样式等。这里描述的特定应用程序是会员管理应用程序,用户可以使用该应用程序维护自己的用户数据,管理员可以根据其角色和相应的优先级管理成员。下面将其称为“web应用程序”。它不仅是数据服务的客户端,一个web站点,还是一个json代理服务,或者网关,连接后端数据服务和最终客户端软件,也就是运行在用户浏览器中的javascripts。因为它将在后续的文章中,javascript的灵活性的打字系统相关duck typing结合的自动生成的严格和广泛的输入系统后端可以让开发人员利用两个世界,使系统灵活的开发但易于维护,提供,当然,两个平衡是正确的。在浏览器中运行的Javascripts。我们采用jQuery + knockoutjs的组合。前者现在很流行,所以我们就不谈了。在整个系统中都使用knockoutjs。它提供了在浏览器应用程序中支持MVVM模式的方法。现在,(json)数据视图模型和相应的视图可以被分离,并在以后以声明的方式绑定在一起。javascript视图模型可以在多个视图甚至应用程序中使用和重用。对于一个数据丰富的应用程序,在一个不断变化的系统中创建和维护这些模型是很繁琐的。幸运的是,其中很大一部分是可以自动生成的。包含在数据服务内部的自动生成的视图和javascript视图模型为应用程序开发人员提供了丰富的资源,以便在稍加修改后在应用层重用它们。为他们节省时间,否则他们会花在冗长、容易出错和重复的工作上。HTML5布局+ CSS3 (less) + jQuery UI + bootstrap。这种组合允许将web应用程序的视图一致地设计、维护和部署到从桌面到移动电话的各种设备上。图:基于服务的会员+系统。3.成员资格+数据模式^成员资格的数据模式+是从前面发布的最小模式扩展而来的狡猾的文章(见这里)。一个好的数据模式非常重要,因为它决定了未来系统的可能性、灵活性、可扩展性和可维护性。希望以下非包含的扩展列表可以使之成为可能:基于Net属性的基于角色的声明式权限机制对于更精细的组织治理有时过于简单和不灵活。但是,由于这里使用了分层角色系统,因此可以使用顶级角色为入口点筛选提供粗粒度的权限。除此之外,一个名为RolePriority的整数类型的属性被添加到Roles数据集中。这个新属性用于描述哪个角色允许执行某个操作,或者根据简单的算术比较,哪个角色的优先级比另一个角色更高(值更大)。拥有操作优先权和/或许可对于层级结构的组织(如企业或政府机构等)来说是很重要的,这样才能很好地运行。它的数值优先级类型使逻辑更简单。一个名为CanBeDeleted的boolean类型的属性被添加到角色数据集中。一些角色不应该在应用程序级别被删除,这是因为在一个基于角色属性的声明式授权系统中(pre Asp. net)。Net 5),一些角色的名称被编译到应用程序代码中。删除这些角色可能会对系统产生意想不到的影响。现在,应用程序可以使用角色的CanBeDeleted值来强制执行一种逻辑,以防止对已编译角色的攻击,在我们的系统中,这些角色应该是诸如管理员之类的顶级通用角色(参见下面的内容)。在UsersInRoles数据集中添加了一个名为SubPriority的整数类型的属性。角色表示一个管理组,有时是一种权限描述,粒度太粗,无法有效地处理具有相同角色的人员间关系。在用户/角色关联数据条目中引入了次优先级,因此在需要时可以进行区分。属性AdminID(它是在Users数据集中引用一个用户的外键)被添加到UsersInRoles数据集中,用于跟踪谁是最后一个创建或修改角色分配的人。为了审计目的,添加了一个新的数据集userrolehistory来跟踪详细的角色分配。当前系统不支持基于投票的角色分配,因此该数据集中的记录可用于使角色分配过程负责。现在,一个用户可能有多个电子邮件地址,用于不同的目的。为了保证这种可能性,Email属性从用户数据集中移除,移动到UserAppMembers数据集中。这样,用户可以为每个应用程序设置一个不同的默认邮箱地址,如果他/她选择这样做的话。用户图标相关的数据属性(Email, IconImg, IconMime, IconLastModified)添加到UserAppMembers数据集中,允许用户为其所属的每个应用程序选择不同的个人图标。添加了一个新的数据集UserDetails,以包含关于用户的自维护的个人详细信息。目前它作为占位符,将在未来被扩展。添加记录用户通信通道的数据集。它们是通信类型和通信。它们记录了在特定应用程序上下文(即依赖于应用程序)内访问用户的各种方式。添加了提供用户层级目录分类的数据集。它们是usergrouptype、UserGroups、UserGroupAdminRoles和usergroupmember。尽管数据服务支持针对任何复杂的数据集(包括用户数据集)进行智能结构化查询,但组织可能仍然发现有必要采用更多静态层次结构分类方案。在现实生活中,用户可以通过多种方式进行分类。例如,一个用户可能属于一个组织中的一个或多个部门,他/她同时也可能是多个跨部门项目、专题小组等的成员。此外,组织可能发布与任何内部成员目录不相同的逻辑成员目录。这三个数据集使用一小部分数据集来涵盖所有这些可能性。UserGroupTypes中的记录表示某种类型的分类方案。数据集用户组为用于表示分类的自引用层次结构集。UserGroupAdminRoles中的记录分配了一组角色,这些角色负责管理组,并且在没有自己的管理角色时隐式地管理子组层次结构。UserGroupMembers集用于将一个用户与一个用户组关联,以便一个用户可以属于多个用户组,而一个用户组可以有多个用户。数据集的公告。用于在可能的应用程序和/或用户组上下文中发布公告。用户组的层次结构特性使得实现允许用户隐式接收父组中的通知的应用程序逻辑成为可能。添加了表示用户在多种类型的社交关系(图)中与其他人如何关联的数据集。它们是userassociationtype, UserAssociations和userassocinvited。成员之间的联系有时是不平等的。例如,一个人与他父母的关系并不等同于父母与那个人的关系。因此,一个成员a应该通过两个记录(a to B record和B to a record)与成员B相关(如果有的话),这两个记录可能不属于同一类型,记录在UserAssociationTypes中表示各种类型的关系。因此,数据集可以用来表示成员之间的定向或非定向(如对等关系)社交图。某种成员关联,如对等类型,需要相互同意,其他的则是自然形成或由第三方分配的。在前一种情况下,必须有一个发起者。初始化记录在userassocinvited数据集中,被邀请的成员可以使用该数据集来决定接受、拒绝或暂停。引入这些数据集是为了使客户机能够支持从简单的联系人列表到复杂的社交网络系统。想要一个像facebook一样的系统,拥有可控的社交图导航?这些数据集可用于提供关系数据支持。表示各种定时事件的数据集。它们是eventtype、EventCalendar和EventCalendarShareCircles。事件可以在应用程序、用户组、个人和连接的社交圈(由EventCalendarShareCircles中的记录表示)上下文的任何组合下可见。用户组的层次结构特性使得实现允许用户隐式共享父组中的事件的应用程序逻辑成为可能。图:会员+数据服务的数据模式示意图。关于它的更多细节可以在数据模型的源代码和数据服务网站托管的相应文档中找到。这些文档作为单独的下载提供,因为它们相当大。数据模型可以在源代码中获得。对于每个数据集,都有对应的集、页和实体数据模型。它们的源代码包含在下载包的Service\共享子目录下的项目中。It服务是这个系统引导阶段的成员资格+数据服务的最小初始数据模式。我们的数据服务生产技术使系统能够在小步骤和小方向上扩展、扩展,甚至缩小,以满足未来更具体的应用需求,可重复的质量和没有太多困难。4. 设置一个解决方案^尝试创建一个Asp。Net MVC 5 web应用程序在适当的目录首先。在我们的例子中,应用程序是使用Visual Studio 2013 Express创建的。这个web应用程序的许多部分在设置时可能已经过时。需要做出一些努力来适当地更新它,以便至少新更新的部分不会彼此冲突。所选根目录下的目录布局应该类似于下面的Libs\MembershipPlusAppLayer。它包含处理应用程序(或业务)逻辑的项目。Libs \ AppLayerTests。它包含单元测试的项目。服务。它包含处理web应用程序和成员资格+数据服务之间通信的项目。网站\ MemberAdminMvc5。它包含了会员管理web应用程序。4.1数据服务相关项目^在解决方案根目录的子目录service \Shared和service \ServiceProxy\Desktop中有两个项目。第一个包含数据服务之间共享数据结构的源代码e和客户机(即考虑中的web应用程序),第二个包含客户机调用数据服务所使用的服务代理的源代码。这两个项目是数据服务分发版的一部分。4.2 Asp。有非常小的变化,Asp. Net成员API ^。Net成员商店和管理器在这里描述,除了它现在被配置为引用上述项目的成员+数据源。由于默认的成员商店和管理器类都预定义了API,无法进一步扩展,所以我们将使用商店和管理器的功能。这篇文章不会涉及更多的细节,这些细节可以在原始文章中找到。数据存储未涉及的那些功能是在下面描述的应用层中实现的。4.3成员+应用层和测试^在当前阶段为它分配了一个空项目。4.4创建和更新web应用程序^请按照这里给出的步骤转换默认的Asp。Net Mvc 5项目。除了这些更改之外,这个更高级的项目还需要做以下工作:在App_Start\Startup. auv .cs文件中的Startup类中添加一个新的静态布尔值字段MemberInitSuccess。通过try封装成员数据服务初始化块。赶上……布洛克:隐藏,收缩,复制Codepublic void ConfigureAuth(IAppBuilder应用) { … 试一试 { cctx。DirectDataAccess = true; Application_ServiceProxy apprepo = new Application_ServiceProxy(); List< Application_>应用= apprepo.LoadEntityByNature (cctx, ApplicationName); 如果(apps == null || apps。数= = 0) { cctx。OverrideExisting = true; var tuple = int . add orupdateentities (cctx, 新Application_Set (), 新Application_ [] { 新Application_ { Name = ApplicationName } }); 应用= tuple.ChangedEntities。长度== 1 & &; IsValidUpdate (tuple.ChangedEntities [0] .OpStatus) ? tuple.ChangedEntities[0]。UpdatedItem:空; cctx。OverrideExisting = false; } 其他的 应用=应用[0]; MemberInitSuccess = true; } 抓 { } } 将一个BaseController类文件添加到wab应用程序的Controllers子目录中,这是一个基类,用于包含应用程序控制器的通用属性和方法。应用程序的所有控制器都可以从它派生。对于像现在这样的动态web应用程序,它的内容更可能是从关系数据源而不是从本地文件检索。因此,一个人既不能依赖web服务器,也不能依赖Asp。Net framework可以有效地控制客户端对静态或缓慢变化的内容的缓存。这是因为无论是web服务器还是Asp。Net framework有关于应用程序特定内容是否被更改的信息。它必须在特定的web应用程序中完成。初始的一个包含一些方法,可以调用这些方法来管理基于最后修改的属性和/或etag属性的站点内容的客户端缓存。发现Asp中基于默认属性的缓存控制机制。Net Mvc 4.0不能很好地按照Http协议处理客户端缓存。包含的方法CheckClientCache和SetClientCacheHeader负责检查内容的客户端缓存状态,并根据内容的last-modified和/或etag属性(如果有的话)设置相同内容的客户端缓存。方法CheckMemberInitStatus用于检查作为成员数据服务客户端的web应用程序的初始化状态。更改项目的控制器(例如AccountController),使其从BaseController类派生。将key="EnableClientCache"项添加到appSettings>网络中的节点。配置文件,并将其值初始化为false。4.5添加无引导源nuget包^Visual Studio默认的Mvc 5项目中只包含的静态层叠样式表(CSS) bootstrap包不容易修改和自定义。我们必须依靠“第三方”来为我们提供主题。这不是我们想要的开发人员,因为我们可以有更多的控制由于引导的“源代码”是公众和动态CSS的形式被称为文件变量较少,嵌套,mixin,运营商和函数可以用来减少信息的重复和维护成本,增加样式一致性。从nuget.org安装“无引导源”。4.6自定义引导^变量。包含bootstrap用来定义样式的主要变量的文件更少。作为一个通用的解决方案,最初的那个包含了一些硬编码的值,至少对于我们的目的来说,这些值可以进一步简化,以与一些基本的值相关。@base-dark color就是控制网站整体配色方案的工具之一。less和其他类似的“可计算”样式表生成系统的美妙之处是,它可以使用一些基本的样式结构来“计算”硬编码的样式,从而产生更一致的视觉效果(参见下面的内容)。4.6.1修改变量。在顶部添加以下变量:复制Code

//@base-dark-color: #333;
//@base-dark-color:  darken(#428BCA, 20%);
//@base-dark-color: darken(#CF4132, 10%);
//@base-dark-color: darken(#DF691E, 10%);
@base-dark-color: darken(#cc5000, 10%);
//@base-dark-color:  darken(#41CF32, 30%);

这只是一个随机选择。你当然可以在这里放更多的“深色”供选择。我们发现,以下对变量进行了修改。更少的文件必须做,以有什么我认为目前的视图在我们目前的使用覆盖率(bootstrap)。预计今后可能还需要更多。重新定义全局“灰色”颜色:隐藏Copy Code@gray-darker:点亮(@base-dark color, 13.5%); @gray-dark:减轻(@base-dark-color, 20%); @gray:减轻(@base-dark-color, 33.5%); @gray-light:减轻(@base-dark-color, 60%); @gray-lighter:减轻(@base-dark-color, 93.5%); 重新定义全局“文本”颜色:隐藏复制Code@brand-primary: @gray-dark; 将导航栏的配色方案与@base-dark-color: Hide联系起来。复制代码//倒转导航条 //重置倒导航条基础 @navbar-inverse-color: @gray-light; @navbar-inverse-bg:减轻(@base-dark-color, 10%); @navbar-inverse-border:变黑(@navbar-inverse-bg, 10%); //反向导航条链接 @navbar-inverse-link-color: @gray-light; @navbar-inverse-link-hover-color: @gray-lighter; @navbar-inverse-link-hover-bg:减轻(@navbar-inverse-bg, 10%); @navbar-inverse-link-active-color: @navbar-inverse-link-hover-color; @navbar-inverse-link-active-bg:变黑(@navbar-inverse-bg, 10%); @navbar-inverse-link-disabled-color: @gray-dark; @navbar-inverse-link-disabled-bg:透明; 将按钮的配色方案与@base-dark-color: Hide联系起来复制Code@btn-default-color: @gray-darker; @btn-default-bg: @gray-light; @btn-default-border:减轻(@gray, 5%); @btn-primary-color: @gray-lighter; @btn-primary-bg: @brand-primary; @btn-primary-border:变黑(@btn-primary-bg, 5%); … 将窗体的配色方案与@base-dark-color: Hide联系起来。复制Code@input-border:减轻(@gray, 10%); … @input-border-focus:减轻(@gray, 5%); 所做的改变将使网站变得不那么丰富多彩(因为它将用更少的颜色来表示),但是在我看来,它们将增加视觉效果的一致性。当然,根据不同的口味,人们可以选择保留原有的口味,也可以自己制作组合。4.6.2创建网站。在web应用程序的内容下面创建一个子目录。然后添加一个名为Site的.less文件。在新创建的文件夹中较少。应该配置自己的less编译程序,将输出文件指向web应用程序的Content子目录下的Site.css文件。将以下内容添加到站点的顶部。刚刚创建的文件更少:隐藏复制Code

@import "..\bootstrap\bootstrap.less";

它将包括所有的引导样式到输出站点.css文件中。由于某些原因,新版本的引导程序放弃了对嵌套菜单的支持,转而支持平面移动样式。由于我们的网站仍然需要支持桌面和大屏幕设备,因此,我们的网站需要要显示的信息种类已经足够复杂,本质上是层层叠叠的,似乎在我们有一种有效处理这些信息的方法之前,我们仍然需要嵌套菜单。幸运的是,这并不是很难做到的。我们发现网站需要添加以下内容支持嵌套菜单的文件更少:隐藏收缩,复制Code

.dropdown-submenu
{
    position:relative;
}
 
.dropdown-submenu>.dropdown-menu
{
    top:0;
    left:100%;
    margin-top:2px;
    margin-left:0px;
    -webkit-border-radius:0 6px 6px 6px;
    -moz-border-radius:0 6px 6px 6px;
    border-radius:0 6px 6px 6px;
}

.dropdown-submenu:hover>.dropdown-menu
{
    display:block;
}

.dropdown-submenu>a:after
{
    display:block;
    content:" ";
    float:right;
    width:0;height:0;
    border-color:transparent;
    border-style:solid;
    border-width:5px 0 5px 5px;
    border-left-color:@gray;
    margin-top:5px;
    margin-right:-10px;
}

.dropdown-submenu:hover>a:after
{
    border-left-color:@gray-darker;
}

.dropdown-submenu.pull-left
{
    float:none;
}

.dropdown-submenu.pull-left>.dropdown-menu
{
    left:-100%;
    margin-left:10px;
    -webkit-border-radius:6px 0 6px 6px;
    -moz-border-radius:6px 0 6px 6px;
    border-radius:6px 0 6px 6px;
}

现在可以删除“~/Content/bootstrap”。css“item from bundle”~/Content/css”在App_Start子目录下的BundleConfig.cs文件中,因为它已经包含在Site.css文件中(见上面)。4.7更改总体布局^ common _Layout。web应用程序的Views\Shared子目录下的cshtml文件被重构,以分解出web应用程序的公共顶栏,将其放入部分视图中,以便除_Layout.cshtml之外,其他视图可以使用它。4.7.1顶部导航栏收缩,复制Code

<divclass="container">
    <divclass="navbar-header">
        <buttontype="button"class="navbar-toggle"data-toggle="collapse"data-target=".navbar-collapse">
            <spanclass="icon-bar"></span>
            <spanclass="icon-bar"></span>
            <spanclass="icon-bar"></span>
        </button>
        @Html.ActionLink("+", "Index", "Home", null, 
              new { @class = "navbar-brand ion-android-social" })
    </div>
    <divclass="navbar-collapse collapse">
        <ulclass="nav navbar-nav">
            <li>@Html.ActionLink("Home", "Index", "Home")</li>
            @if (Request.IsAuthenticated)
            {
                <liclass="dropdown">
                    <adata-toggle="dropdown"class="dropdown-toggle"href="#">
                       Organizers<bclass="caret"></b>
                    </a>
                    <ulclass="dropdown-menu">
                        <liclass="dropdown-submenu">
                            <ahref="#">Bookmarks</a>
                            <ulclass="dropdown-menu"role="menu">
                                <li>
            @Html.ActionLink("By Data Source", "Bookmarks", "Home")
                                </li>
                                <li>
            @Html.ActionLink("By Categories", "CategBookmarks", "Home")
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <liclass="dropdown">
                    <adata-toggle="dropdown"class="dropdown-toggle"href="#">
                        Settings<bclass="caret"></b>
                    </a>
                    <ulclass="dropdown-menu"role="menu">
                        <liclass="dropdown-submenu">
                            <ahref="#">Account</a>
                            <ulclass="dropdown-menu"role="menu">
                                <li>
            @Html.ActionLink("Change account info", "ChangeAccountInfo", "Account")
                                </li>
                                <li>
            @Html.ActionLink("Change preferences", "EditUserPreferences", "Account")
                                </li>
                                <li>
            @Html.ActionLink("Add/Change profile", "UserDetails", "Account")
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <liclass="dropdown">
                    <adata-toggle="dropdown"class="dropdown-toggle">
                        Admin<bclass="caret"></b>
                    </a>
                    <ulclass="dropdown-menu">
                        <li>
            @Html.ActionLink("Admin Users", "UserAdmin", "Admin")
                        </li>
                        <li>
            @Html.ActionLink("Admin Roles", "RoleAdmin", "Admin")
                        </li>
                        <liclass="dropdown-submenu">
                            <ahref="#">Statistics</a>
                            <ulclass="dropdown-menu">
                                <li>
            @Html.ActionLink("Online Users", "OnlineUsers", "Admin")
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
            }
            <li>@Html.ActionLink("About", "About", "Home")</li>
            @*<li>@Html.ActionLink("Contact", "Contact", "Home")</li>*@
        </ul>
        @Html.Partial("_LoginPartial")
    </div>
</div>

其中进一步包括_LoginPartial。cshtml处理用户的登录/注销,具体取决于用户的当前登录状态。4.7.2更改登录和注册视图^有两个视图名为登录。cshtml并注册。视图\帐户子目录下的cshtml。这两个视图包含关于演示用户的信息。在使用演示数据样例查看演示之后,应该删除这些信息(参见下面的内容),因为这些信息与任何其他成员数据源都不相关。4.8“Hello world !”^网站应该准备好第一次运行。如果有任何问题,请在下面的评论区告诉我。图:“Hello world !”按照上面的步骤配置.less文件后,更改颜色方案很容易。我们只需要更改@base-dark-color变量(参见这里)。下面是几个例子。图:示例皮肤。5. 设置数据服务^从会员+数据服务包中提取文件到一个文件夹,为它配置一个网站(它是一个ASP。NET MVC 4 web应用程序)。在你的系统内启用WCF的HTTP激活。基本上是这样。如果您需要持久化您的更改,至少服务站点下的App_Data\MembershipPlus\Data子目录需要有适当的权限。它应该允许用户IIS_IUSRS的写权限。警告:这是用于评估目的的系统演示/测试版本。它基于一个瞬态序列化方法。请不要将其用于长时间数据持久性或用于支持生产系统。5.1编译文档^在源代码的根目录下有一个文档子目录,其中包含一个沙堡项目,可以用来编译客户端(即web应用端)编程的文档。但是在编译文档之前,请确保完成以下工作:安装Sandcastle(如果还没有安装的话)。对web应用程序的解决方案进行编译,以便生成xml文档文件。文档的默认输出路径为..\..\DataService\网站\文档\ClientAPI\相对于文档目录。确保这是一个允许的输出目录。如果没有,将其更改为适当的。如果上述输出目录与数据服务网站的Documents\ClientAPI子目录不一致,则删除后者的所有内容(如果有的话),并将前者内部生成的所有文档文件复制到后者。6. 连接到数据服务^ 6.1设置机器密钥^成员资格提供者使用机器密钥(web应用程序的)哈希密码和加密身份验证cookie。为了更好地控制会员系统(参见,例如,这里),不要使用系统默认值,应该通过添加以下节点Hide来设置它的值。复制Code

<machineKey
    validationKey="..."
    decryptionKey="..."
    validation="SHA1"
    decryption="AES"
/>

在& lt; system.web>节点内部的网络。配置文件,并为validationKey和decryptionKey生成一个适当的值。当然,不应该将本文提供的值用于任何实际用途。6.2将WCF配置为客户端^在解决方案的服务\ServiceProxy\桌面子目录中有一个自动生成的名为app.config的文件。它包含成员资格+数据服务公开的所有端点。复制隐藏的内容复制Code

<system.serviceModel>
   ...
</system.serviceModel>

节点转换为web应用程序的web中的对应节点。配置文件。剩余的servicedomain__占位符(或者它的当前值是什么)应该被替换为成员+数据服务的实际根url,该服务是在reader的测试环境,例如http://localhost/memberplus。这里的说明也可能有用。6.3配置会员商店^在<appSettings>下面插入以下节点;节点内部的网络。web应用程序的配置文件隐藏复制Code

<addkey="ApplicationName"value="MemberPlusManager"/>
<addkey="WriteAuthExceptionsToEventLog"value="false"/>
<addkey="RequiresUniqueUserEmail"value="true"/>
<addkey="UserApprovedOnAddition"value="true"/>
<addkey="ThrowOnDeletePopulatedRole"value="true"/>
<addkey="DeleteUserMembershipOnly"value="true"/>
<addkey="PasswordAttemptWindow"value="20"/>
<addkey="MaxInvalidPasswordAttempts"value="5"/>
<addkey="UserStoreAutoCleanupRoles"value="true"/>

其中“MemberPlusManager”是应用程序的名称。然后为成员资格+数据服务配置成员资格存储。欲了解更多细节,请阅读这篇文章。6.4选择一个样本数据源^数据在内存中的数据库位于App_Data\MembershipPlus\数据子目录的web应用程序。应用程序的初始系统应该以一个空目录开始,并根据应用程序的需要设置数据。这将在下一节中介绍。但出于演示或测试的目的,不重新启动并每次设置数据可能更有效。如果是这种情况,可以从上面下载包中包含的数据源中选择一个,并将那里的所有文件复制到所述目录中。它可能很有用,因为它已经包含了一些初始数据,包括对用户(sysadmin和demo-user-a)、角色(Administrators和Administrators >系统)和用户的角色添加。复制后,按下“加载数据库”按钮将其加载。再运行一次^ 6.5.1尝试演示^如果还没有,先启动第5节中配置的数据服务。现在,使用选择的示例数据再次在调试器中启动web应用程序,可以按照上面的说明加载这些数据。以用户名sysadmin登录,顶部导航栏包含其他菜单,如下所示:图:登录后显示的顶部导航栏。注意,目前显示的新菜单中没有一个指向已实现的操作。6.5.2重新开始^在演示之后,是时候做一些动作了。删除web应用程序的App_Data\MembershipPlus\Data子目录中的所有文件,并再次加载数据库。接下来运行web应用程序(当然是在调试器中)。虽然表面上运行的“hello world”似乎与之前的“hello world”没有任何区别,但如果系统配置正确,应用程序(在上面所示的提供程序配置中定义的名称,即“MemberPlusManager”)会自动注册。可以使用data service management前端显示应用程序条目,后面将对此进行描述。下一步是注册一些初始用户。可以在web应用程序的用户注册页面内完成,如下图所示:为了进一步操作,一个人至少要注册一个用户,比如“sysadmin”,它将是下面描述的根用户。由于我们使用的是内存中的关系数据后端,因此应该在长时间空闲后回收数据服务管理站点的应用程序池之前将其保存到磁盘(有关说明,请参阅下面的说明)。7. 初始化会员数据^数据服务有它自己的管理网站。它是一种通用的、最完整的、智能的数据管理前端,它是根据从上面介绍的关系数据模式扩展的模式构建的。它是为系统管理员内部的一个安全的本地网络,大多数创建,读取,更新和删除(CRUD)操作可以单独使用这个前端执行。但是,除了可以编码到用于自动生产系统的当前扩展数据模式规范中的内容外,它没有强制执行更多特定于应用程序的逻辑/信息。尽管将来可以将更多的信息转移到自动处理系统中,但仍然有更多的细节需要web应用层来处理。本节简要介绍数据服务管理前端的使用。该流程的另一个目标是初始化成员资格+数据源,以便更多具有适当授权的用户可以在internet上的任何位置通过更用户友好的web界面以安全和受控的方式管理成员资格。现在的文章和后面的文章都是关于它的。通过单击主页中的“data Source”选项卡可以到达数据管理页面。7.1使用数据服务操作前端^ 7.1.1数据库层^数据库页面包含所有数据集(表)的列表和数据源内部数据关系的示意图。除了在清单中,根据所使用的支持关系数据后端类型,有不同的操作按钮集。对于当前内存中的关系数据后端,有load和save数据库按钮,可用于手动控制在开发或测试期间如何持久化数据。数据库是在启动数据服务管理站点时加载的。如果在一些重要操作之后再次手动加载数据库,那么这些操作将被丢弃,数据库将恢复上次加载时的状态。但是,如果在这里进行了一些非琐碎的操作后手动保存数据库,那么更改将被保存,下次重新加载数据库时,它将立即从保存之后的状态开始。内存中关系数据后端的数据文件位于数据服务管理网站的App_Data\MembershipPlus\ data子目录中。目录最初是不存在的。它将在第一次点击“Save Database”按钮后创建。正如预期的那样,可以保存多个版本的数据(文件),并根据开发需要(作为整体)加载它们。图:内存中演示/测试/开发关系数据后端的数据库页面。对于由传统关系数据库引擎支持的关系数据后端,当数据库尚未创建时,有一个“创建数据库”按钮。单击该按钮后,如果正确配置了数据服务,从而使操作成功,那么“Create Database”按钮将在下一次刷新页面时消失。7.1.2数据集级别^数据集级别的页面提供CRUD操作供用户执行。页面有to模式,即ViewMode和Edit模式。模式由页面右上角对应的按钮控制。以应用程序数据集为例:图:在查看模式下,数据集页面上的编辑模式转换按钮。该页面默认情况下不显示任何数据。这是因为用户没有为要放在第一个页面上的数据指定排序和筛选查询条件。用户界面的构造要求用户在执行其他操作之前必须指定至少一个完整的排序表达式(属性+方向)。如果用户不熟悉可排序的数据集的属性名称,可以将输入光标放在“Sort By”标签旁边的文本框内,使用向下箭头键列出可用的值。例如,以下是用户在使用应用程序数据集时看到的。图:应用程序视图页面,最初加载时。选择一个值,说Name,系统将引导用户提供下一个可用值。当用户已经熟悉特定的数据集时,他/她总是可以输入属性名称的前几个字母,当提供足够的信息时,系统可以自动完成。当排序表达式处于完整状态后,显示按钮会出现,如下图所示:显示按钮出现并打开筛选框。点击显示按钮(红色圆圈内),将显示数据的第一页。目前只有一个申请。它的详细信息可以通过选择它来查看:Figure:应用程序在前一节讨论的web应用程序的预览运行中自动注册。如图所示,项目的DisplayName为null。可以为应用程序设置一个更友好的名称。这可以通过先进入编辑模式来实现。然后,按照与上面描述的过程相同的步骤显示这些项。DisplayName属性有一个相应的文本框。输入一个显示名称,如“Membership+ Management System”,点击上面的Commit按钮,将其保存到数据库中,如下图所示:一个应用程序实体集合的修改在“Commit”时被保存到数据库中。在“提交”之前,可以对多个记录进行多次更改。提交操作将在一个步骤中将所有更改保存到数据库中。如果使用内存中的数据库作为后端,用户还需要考虑一个操作。也就是说,他/她可以选择将更改持久化到磁盘或回滚更改或者把它留在内存中。如上所述,持久化或回滚更改是在数据库页面中使用“保存数据库”或“加载数据库”按钮执行的。7.2添加根角色和根用户^在预热后,我们需要继续初始化会员管理系统。由于这是一个基于角色优先级的成员管理系统,所以如果不创建根角色并使用web应用程序之外的方法将其分配给根用户,web应用程序(manager)就无法正常工作。根角色必须具有系统的最高优先级,根用户必须具有根角色的最高相对优先级。这个设置,根用户可以使用web应用程序界面添加aditional高水平管理的角色,并将它们分配给所选定的几个用户可以做同样的事情(分享高层经理的工作负载),直到整个行政组织形成,以有序的方式。这并不排除根管理器单独在小型组织中或在组织处于初始设置阶段的情况下完成所有初始分配工作的可能性。7.2.1添加根角色^到角色数据集页面,进入编辑模式。尽管数据集为空,但仍建议尝试先列出数据,遵循上述过程。当页面处于列表模式时,新添加的项目将在添加后立即列出。否则,只有当用户试图列出新添加的项时,才会看到它们!图:编辑和列表模式下的角色数据集页面。“添加”按钮用红色圈起来。点击“添加”按钮,添加第一个类别角色“Administrators”,如下图所示。图:角色添加对话框。外键ApplicationID和ParentID在右边有打开相应实体选择对话框的按钮。接下来为RoleName、DisplayName(可选)和RolePriority属性设置适当的值。由于这应该是用于各种管理角色的类别角色,因此应该为其设置足够高的优先级。这里我们将其设置为任意值10000,因为它用于演示目的。一个设计良好的角色系统应该有容易记住和直观的角色优先级的价值。单击ApplicationID属性旁边的按钮,打开如下所示的应用程序选择对话框。图:关联的应用程序选择对话框。使用上述过程查找并选择新创建的应用程序,然后单击“OK”按钮。不应该为这个顶级角色选择任何ParentID。再次单击“OK”按钮,我们的第一个角色“Administrators”被添加到数据源中,如下所示。图:新添加的“Administrators”角色。名为“System”的根角色应该位于刚刚添加的分类角色之下。因此,应该遵循与上面相同的过程,为ApplicationID外键属性选择相同的应用程序,为ParentID外键选择刚刚添加的“Administrators”角色。生成以下角色列表。图:添加了根角色。角色层次结构的显示。注意,角色层次结构下的所有角色都必须引用相同的应用程序。如果没有,结果是不期望的!好了,添加了所需的最小角色。下一个任务是将它们分配给用户。把根角色分配给根用户^我们需要把根角色分配给管理员。到根用户“sysadmin”。转到UsersInRoles数据集的页面,进入编辑模式,然后进入列表模式,并在数据集中添加一个关联实体,该实体必须RoleID指向根角色,UserID属性指向根用户,具有足够大的次优先级(或相对优先级)。可以保留AdminID属性(设置空值),因为它是在系统外部添加的。成功添加后,将显示以下内容。图:新增的角色分配记录。系统有一个名为UsersRoleHistories的数据集,用于审计目的,它记录用户的角色历史以及谁执行了任务。我们不需要为根目录输入任何条目,因为它是在系统外部完成的。^ 7.3.1 UserGroupTypes ^ UserGroups数据集包含分层的用户分类(目录)数据。由于用户可以属于Membership+数据模式中的多个组,我们可以为各种用户分类模式使用相同的数据集,例如用户可以bel组织中的某个部门、逻辑目录、项目或社会团体等。所有这些都可以通过单个数据集来描述,即具有不同组类型的UserGroups集。现在应该预先初始化该类型。UserGroupTypes数据集的标识属性ID不会自动生成。所以应该由输入器手动分配。导航到UserGroupTypes页面,输入edit + list模式并输入一组感兴趣的类型。这是一个暂定的列表图:暂定的用户组类型。7.3.2其他类型^初值也用类似的方法插入到样本“Communication types”和“UserAssociationTypes”数据集中。保存刚刚修改过的数据集,因为我们使用的是内存中的关系数据后端。在保存之后,将生成一个初始样本数据集,该数据集可以用作一个起点,从这里可以展开各种测试。然后将数据服务网站(不是本文的web应用程序!)的App_Data\MembershipPlus\Data子目录中的文件复制到其他地方,以便总是可以复制回来重新开始。8. 历史^ 2014-02-05。文章版本1.0.0,初始发布。2014-02-22文章版本1.0.1,更新到目标。net 4.5.1。如果读者对Git源码控制系统有足够的了解,可以在github.com上查看Git库。本文的源代码是在codeproject-1分支上维护的,也就是这里。 本文转载于:http://www.diyabc.com/frontweb/news17327.html

posted @ 2020-08-13 02:20  Dincat  阅读(187)  评论(0编辑  收藏  举报