XAF How to: 实现一个WCF Application Server 并配置它的客户端应用

主题描述了如何实现一个 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 身份验证属性设置 trueIfAuthenticationActiveDirectory 使用初始化 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"。

 
现在可以运行应用服务器客户端应用程序。在解决方案资源管理器中应用程序服务器项目设置启动项目,并且运行服务器运行客户端应用程序右击解决方案资源管理器应用程序项目然后选择调试 |启动实例显示了服务器客户端
原文地址:https://www.cnblogs.com/foreachlife/p/xafmiddletier.html