本主题描述了如何实现一个 WCF 中间层应用程序服务器及如何配置 XAF客户端连接到此服务器。

注意
本主题演示可以由解决方案向导自动生成的代码。执行操作时,如果你想要在现有的 XAF 解决方案中实现的显示的功能。如果您要创建一个新的 XAF 解决方案,请使用向导。
 
完整的样例项目是在 http://www.devexpress.com/example=E4599
 
1.打开现有的 XAF 解决方案,启用新的安全系统,创建几个用户帐户。如果您没有此现有的解决方案,看这里如何创建一个基于客户端的安全(2 层架构)教程
2.向 XAF 解决方案中添加一个控制台应用程序项目。这个项目将代表在此示例中的应用程序服务器。
3.将引用添加到您的 XAF 解决方案 (例如,MySolution.Module、 MySolution.Module.Win 和 MySolution.Module.Web) 的模块项目。右键项目,单击创建新项目,然后在对话框中选择“添加引用......” ,切换到项目选项卡,选择模块项目,并单击确定。

4.打开新创建的项目的 Program.cs (Program.vb) 文件。将以下代码添加到 Main 方法 (在此示例中,假定您的 XAF 解决方案称为"MySolution")。

using System;
using System.Collections.Generic;
using System.ServiceModel;
using DevExpress.Persistent.Base;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.MiddleTier;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Security.ClientServer;
using DevExpress.ExpressApp.Security.ClientServer.Wcf;
using DevExpress.ExpressApp.Security.Strategy;
using DevExpress.ExpressApp.Web.SystemModule;
using DevExpress.ExpressApp.Win.SystemModule;
using DevExpress.ExpressApp.Xpo;
// ...
static void Main() {
    try {
        Console.WriteLine("Starting...");
        DataSet dataSet = new DataSet();
        string connectionString =
            "Integrated Security=SSPI;Pooling=false;Data Source=(local);Initial Catalog=MySolution";
        ValueManager.ValueManagerType = typeof(MultiThreadValueManager<>).GetGenericTypeDefinition();

        ServerApplication serverApplication = new ServerApplication();
        serverApplication.ApplicationName = "MySolution";
        serverApplication.Modules.Add(new MySolution.Module.MySolutionModule());
        serverApplication.Modules.Add(new SystemWindowsFormsModule());
        serverApplication.Modules.Add(new SystemAspNetModule());
        serverApplication.CreateCustomObjectSpaceProvider += delegate(object sender, CreateCustomObjectSpaceProviderEventArgs e) {
            e.ObjectSpaceProvider = new XPObjectSpaceProvider(connectionString, null);
        };
        serverApplication.DatabaseVersionMismatch += delegate(object sender, DatabaseVersionMismatchEventArgs e) {
            e.Updater.Update();
            e.Handled = true;
        };

        Console.WriteLine("Setup...");
        serverApplication.Setup();
        Console.WriteLine("CheckCompatibility...");
        serverApplication.CheckCompatibility();
        serverApplication.Dispose();

        Console.WriteLine("Starting server...");
        QueryRequestSecurityStrategyHandler securityProviderHandler = delegate() {
            return new SecurityStrategyComplex(
                typeof(SecuritySystemUser), typeof(SecuritySystemRole), new AuthenticationStandard());
        };

        IDisposable[] disposable;
        IDataLayer dataLayer = new SimpleDataLayer(XpoTypesInfoHelper.GetXpoTypeInfoSource().XPDictionary,
                                         DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateProviderFromString(connectionString,
                                         DevExpress.Xpo.DB.AutoCreateOption.None, out disposable));
        SecuredDataServer dataServer = new SecuredDataServer(dataLayer, securityProviderHandler);

        ServiceHost serviceHost = new ServiceHost(new WcfSecuredDataServer(dataServer));
        serviceHost.AddServiceEndpoint(typeof(IWcfSecuredDataServer),
            WcfDataServerHelper.CreateDefaultBinding(), "http://localhost:1451/DataServer");
        serviceHost.Open();

        Console.WriteLine("Server is started. Press Enter to stop.");
        Console.ReadLine();
        Console.WriteLine("Stopping...");
        serviceHost.Close();
        Console.WriteLine("Server is stopped.");
    }
    catch(Exception e) {
        Console.WriteLine("Exception occurs: " + e.Message);
        Console.WriteLine("Press Enter to close.");
        Console.ReadLine();
    }
}

注意

  1. ServerApplication.ApplicationName 属性值是客户端应用程序的名称 (即 XafApplication.ApplicationName) 相同。
  2. ServerApplication.Modules 集合应包含由客户端应用程序直接引用的模块。要查看哪些客户端应用程序要求哪些模块,可以在 WinApplication/WebApplication 的InitializeComponent方法中找到。
  3. QueryRequestSecurityStrategyHandler 对象指定了用户类型、 角色类型和身份验证。
  4. 服务终结点是通过 ServiceHost.AddServiceEndpoint 方法添加的。
  5. 如果您使用自定义权限请求和自定义登录参数,在用户初始化数据服务器之前注册通过静态的 WcfDataServerHelper.AddKnownType 方法。
  6. 如果您想要使用一个自定义的绑定对象,不要使用 WcfDataServerHelper.CreateDefaultBinding 方法。自己创建所需的绑定对象并将它传递给ServiceHost.AddServiceEndpoint 方法。
  7. 当使用 AuthenticationActiveDirectory 时, all the methods of the application server should be invoked in the caller's context (a Windows account under which the client application is running). Refer to the Delegation and Impersonation with WCF and Security in Remoting articles in MSDN for more details on how this can be done, depending on the transport technology used. For instance, in the case of WCF, you can modify the ServiceAuthorizationBehavior.ImpersonateCallerForAllOperations property in the code of your service.

  8. 打开 Windows 窗体应用程序项目的 Program.cs (Program.vb) 文件。修改 Main 方法,如下所示。
using System.ServiceModel;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Security.ClientServer;
using DevExpress.ExpressApp.Security.ClientServer.Wcf;
// ...
[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    EditModelPermission.AlwaysGranted = System.Diagnostics.Debugger.IsAttached;
    MySolutionWindowsFormsApplication winApplication = new MySolutionWindowsFormsApplication();
    string connectionString = "http://localhost:1451/DataServer";
    try {
        WcfSecuredDataServerClient clientDataServer = new WcfSecuredDataServerClient(
            WcfDataServerHelper.CreateDefaultBinding(), new EndpointAddress(connectionString));
        ServerSecurityClient securityClient = new ServerSecurityClient(clientDataServer, new ClientInfoFactory());
        securityClient.IsSupportChangePassword = true;
        winApplication.ApplicationName = "MySolution";
        winApplication.Security = securityClient;
        winApplication.CreateCustomObjectSpaceProvider += delegate(
            object sender, CreateCustomObjectSpaceProviderEventArgs e) {
            e.ObjectSpaceProvider = new DataServerObjectSpaceProvider(clientDataServer, securityClient);
        };
        winApplication.Setup();
        winApplication.Start();
        clientDataServer.Close();
    }
    catch(Exception e) {
        winApplication.HandleException(e);
    }
}
  1. ServerSecurityClient.IsSupportChangePassword 属性指示可以通过 ChangePasswordByUser 和 ResetPasswords 操作更改用户密码。如果在服务器端使用AuthenticationStandard 身份验证,则将此属性设置为 true。IfAuthenticationActiveDirectory 使用时,无需初始化的 IsSupportChangePassword 属性,因为它的默认值为 false。请注意,此设置只会影响的 ChangePasswordByUser 和 ResetPasswords 操作的可见性,请不要授予写权限给用户的 StoredPassword 属性。创建相应的成员级别权限,以允许非管理用户更改他们的密码。
    • 备注:


      在调试时,服务器主机名是在连接字符串中的"localhost"。更改根据服务器端设置的端口号。(因为它默认应用程序项目中完成的),您也可以从通过配置应用程序对象的配置文件读取连接字符串。为简单起见在这里连接是硬编码的。
      如果您使用自定义权限请求和自定义登录参数,在用户客户端应用程序在初始化之前注册通过静态的 WcfDataServerHelper.AddKnownType 方法。
       
  2. 当应用程序服务器正在使用中时,在服务器端执行兼容性检查。在 XafApplication.DatabaseVersionMismatch 的事件发生时,应无条件地引发异常。编辑WinApplication.cs (WinApplication.vb) 文件,并按以下方式修改 DatabaseVersionMismatchevent 处理程序。
public partial class MySolutionWindowsFormsApplication : WinApplication {
    //...
   private void MySolutionWindowsFormsApplication_DatabaseVersionMismatch(
        object sender, DevExpress.ExpressApp.DatabaseVersionMismatchEventArgs e) {
        throw new InvalidOperationException(
            "The application cannot connect to the specified database " +
            "because the latter does not exist or its version is older " +
            "than that of the application.");
        }
    }
}
  1. 编辑 Module.cs (Module.vb) 文件位于与平台无关模块项目(即你的XXX.Module项目)。注册以下列方式使用的安全类型。(就是用户和角色所使用的类型)

using DevExpress.ExpressApp.Security.Strategy;
// ...
public sealed partial class MySolutionModule : ModuleBase {
    // ...
    protected override IEnumerable<Type> GetDeclaredExportedTypes() {
        List<Type> result = new List<Type>(base.GetDeclaredExportedTypes());
        result.AddRange(new Type[] { typeof(SecuritySystemUser), typeof(SecuritySystemRole) });
        return result;
    }
}

上面的代码需要引用 DevExpress.ExpressApp.Security.v15.2 程序集。

默认情况下,导航栏中不会显示角色的列表,这个行为与2层架构不同,如果想要显示角色列表,需要手动的在xafml中增加角色列表,列表的名称是:"SecuritySystemRole_ListView"。

 
现在你可以运行在应用服务器和客户端应用程序。在解决方案资源管理器中将应用程序服务器项目设置为启动项目,并且运行服务器。要运行客户端应用程序,右击解决方案资源管理器中的应用程序项目,然后选择调试 |启动新实例。下图显示了服务器和客户端。

XAF How to: 实现一个WCF Application Server 并配置它的客户端应用的更多相关文章

  1. 如果你想深刻理解ASP.NET Core请求处理管道,可以试着写一个自定义的Server

    我们在上面对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了详细介绍(<聊聊ASP.NET Core默认提供的这个跨平台的服务器——KestrelServer& ...

  2. WCF入门教程2——创建第一个WCF程序

    本节目标 掌握接口 理解契约式编程 创建宿主程序 创建客户端程序访问服务 什么是接口 认识一下接口 必须知道的接口特性 接口不可以被实例化(常作为类型使用) 实现类必须实现接口的所有方法(抽象类除外) ...

  3. Step by Step 创建一个WCF Service

    原创地址:http://www.cnblogs.com/jfzhu/p/4025448.html 转载请注明出处 (一)创建WCF Service (1)创建WCF Service类库 创建一个Cla ...

  4. 跟我一起学WCF(4)——第一个WCF程序

    一.引言 前面几篇文章分享了.NET 平台下其他几种分布式技术,然而前面几种分布式技术专注于某一特定的领域,并且具有不同编程接口,这使得开发人员需要掌握多个API的使用.基于这样的原因,微软在.NET ...

  5. linux/win7下安装websphere application server

    说明: 1.参考网址:http://www.ibm.com/developerworks/cn/aix/library/au-wasonlinux/ 2.在ibm官网上下载websphere appl ...

  6. 在 WebSphere Application Server V7 集群环境中管理 HTTP session[阅读]

    http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1012_dingsj_wascluster/1012_ding ...

  7. JBoss AS7(Application Server 7)的Standalone模式和Domain模式

    JBoss AS7(Application Server 7)支持两种引导模式:standalone和domain(域). Standalone模式对于很多应用,并不需要domain管理能力,JBos ...

  8. BizTalk Server 2016配置 WCF SAP Adapter

    BizTalk Server 2016配置 WCF SAP Adapter 最近公司内部需要使用BizTalk与SAP 系统进行对接,虽然SAP/PI可以以发布WebService 的方式实现与外部系 ...

  9. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

随机推荐

  1. windows下编译chromium浏览器的15个流程整理

    编译chromium 系统为windows, 国内在windows上编译chromium的资料比较少, 我这篇文章只能作为参考, 记录我遇到的一些问题,因为chromium团队也会修改了代码,或者编译 ...

  2. 面试题目——《CC150》智力题

    面试题6.1:有20瓶药丸,其中19瓶装有1克/粒的药丸,余下一瓶装有1.1克/粒的药丸.给你一台称重精准的天平,怎么找出比较重的那瓶药丸?天平只能用一次. 思路:第1瓶取1颗,第2瓶取2颗....最 ...

  3. NYOJ 99单词拼接(有向图的欧拉(回)路)

    /* NYOJ 99单词拼接: 思路:欧拉回路或者欧拉路的搜索! 注意:是有向图的!不要当成无向图,否则在在搜索之前的判断中因为判断有无导致不必要的搜索,以致TLE! 有向图的欧拉路:abs(In[i ...

  4. 如何让vim编辑器永久显示行号

    在Linux环境下的编辑器有vi.vim.gedit等等.进入这些编辑器之后,为了方便我们需要编辑器显示出当前的行号,可偏偏编辑器默认是不会显示行号的.我们有二种办法可以解决: 第一种是,手动显示:在 ...

  5. Codeforces 260 A - A. Laptops

    题目链接:http://codeforces.com/contest/456/problem/A 解题报告:有n种电脑,给出每台电脑的价格和质量,要你判断出有没有一种电脑的价格小于另一种电脑但质量却大 ...

  6. [知识点]Cantor展开

    // 此博文为迁移而来,写于2015年3月14日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vtyo.html 1.含 ...

  7. multi-CPU, multi-core and hyper-thread--转

    原文地址:http://stackoverflow.com/questions/680684/multi-cpu-multi-core-and-hyper-thread Multi-CPU was t ...

  8. C#获取枚举描述代码

    public class MusterEnum { /// 获取枚举的描述信息 /// </summary> /// <param name="e">传入枚 ...

  9. 【转】 Mybatis/Ibatis,数据库操作的返回值

    该问题,我百度了下,根本没发现什么有价值的文章:还是看源代码(详见最后附录)中的注释,最有效了!insert,返回值是:新插入行的主键(primary key):需要包含<selectKey&g ...

  10. TMS320C54x系列DSP的CPU与外设&mdash;&mdash;第3章 存储器

    第3章  存储器 本章介绍了TMS320C54x DSP存储器的构成和操作.一般来说,C54x器件共有192K 16位字的存储窨,这个空间分成3个专用的部分:64K字程序.64K字数据和64K字I/O ...