65.9K
CodeProject 正在变化。 阅读更多。
Home

一种更灵活、更安全的 ASP.NET Web.config 文件配置 Silverlight 应用程序的方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.18/5 (7投票s)

2010年2月2日

CPOL

6分钟阅读

viewsIcon

34534

downloadIcon

202

本文介绍了一种更灵活、更安全的配置 Silverlight 应用程序的方法,即使用 ASP.NET 宿主应用程序的 Web.config 文件。

引言

本文介绍了一种更灵活、更安全的配置 Silverlight 应用程序的方法,即使用 ASP.NET 宿主应用程序的 Web.config 文件。

背景

在我之前的文章《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》中,我介绍了一种将配置信息从 ASP.NET 宿主应用程序的 Web.config 文件传递到 Silverlight 应用程序的方法。我注意到该方法存在两个问题:

  1. 由于配置信息以明文形式写入宿主 ASPX 页面,因此安全性较低。
  2. 由于使用等号分隔的键值对,然后用逗号分隔,因此在处理 `=` 和逗号等特殊字符时存在困难。

一些读者还指出,该应用程序在 Firefox 中工作存在一些困难。这并不是 Silverlight 的问题,而是 Firefox 的问题。在本文中,在我对宿主 ASP.NET 页面做了一些小的更改后,该应用程序在我的计算机上的 Firefox 中显示出来了。

尽管我们可以为所有这些问题找到解决方法,但最好从一开始就避免这些问题。

本文旨在介绍一种更灵活、更安全的配置 Silverlight 应用程序的方法,即使用 ASP.NET 宿主应用程序的 Web.config 文件。本文的思路是使用 WCF 服务将配置信息传递到 Silverlight 应用程序。WCF 服务将在 ASP.NET 宿主应用程序内部创建,因此 Silverlight 应用程序可以使用“相对路径”访问 WCF 服务。在部署时,只要 WCF 服务与宿主 ASPX 页面一起部署,Silverlight 应用程序就可以轻松找到并使用它。本文介绍的方法不会出现任何可移植性问题,因为对 WCF 服务的访问是使用“相对路径”进行的。

我将不会详细介绍如何在 Visual Studio 中创建 Silverlight 应用程序。如果您不熟悉,可以参考文章《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》和《一个简单的灵活的 Silverlight 启动屏幕》。如果您不熟悉如何创建 WCF 服务并在 Silverlight 应用程序中使用它们,可以参考《在同一个 Visual Studio 解决方案中并发开发 Silverlight 和 WCF 应用程序》。

本文中的示例代码与《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》中的代码非常相似,但有三个主要区别:

  1. 已删除 Default.aspx 中用于将 InitParams 传递给 Silverlight 应用程序的 ASP.NET Literal 对象。本文不再使用它。
  2. 在 ASP.NET 宿主应用程序中创建了一个 WCF 服务“SilverlightConfiguration.svc”,用于从 Web.config 文件读取配置信息。
  3. 在 Silverlight 应用程序中,通过“相对路径”调用 WCF 服务来获取配置信息。

示例代码是用 Visual Studio 2008 和 Silverlight 3 编写的。

示例 Visual Studio 解决方案的整体结构

Solution Explorer

从上图可以看出,Visual Studio 解决方案有两个项目。一个是 Silverlight 应用程序,另一个是 ASP.NET 宿主应用程序。在 ASP.NET 项目中,我们有以下主要组件:

  1. Default.aspx 文件,托管 Silverlight 应用程序。
  2. ISilverlightConfiguration.cs”和“SilverlightConfiguration.svc”文件,提供 Silverlight 应用程序获取配置信息的 WCF 服务。
  3. Web.config 文件,配置信息写入其中。

在 Silverlight 项目中,我们可以看到以下内容:

  1. 一个 C# 文件,“WCFServiceFactory.cs”,用于实现一个简单的类,创建 WCF 服务的引用接口。
  2. App.xaml.cs 文件,在此调用 WCF 服务以检索配置信息。

现在,我将提供一些详细的解释。我将从 ASP.NET 宿主应用程序开始。

宿主 ASP.NET 应用程序项目

在 ASP.NET 应用程序中,Silverlight 应用程序托管在 Default.aspx 文件中。由于我们不再像在《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》中那样使用“InitParams”参数传递信息,因此 ASP.NET Literal 对象已被移除。

<%@ Page Language="C#" AutoEventWireup="true" EnableViewState="false"
    CodeBehind="Default.aspx.cs" 
    Inherits="SilverlightBetterConfigurationWeb.Default" %>
   
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Silverlight Configuration Demonstration</title>
    
    <!-- Link the Microsoft generated style -->
    <link href="Styles/SilverlightDefault.css" rel="stylesheet" type="text/css" />
    
    <!-- Link the Microsoft generated JAVA scripts -->
    <script src="JS/Silverlight.js" type="text/javascript"></script>
    <script src="JS/SilverlightDefault.js" type="text/javascript"></script>
</head>
 
<body>
    <form id="frmMain" runat="server">
    <div style="text-align: center">
        <object data="data:application/x-silverlight-2,"
            type="application/x-silverlight-2"
            width="700px" height="500px">
    <param name="source" value="ClientBin/SilverlightBetterConfiguration.xap"/>
    <param name="onError" value="onSilverlightError" />
    <param name="background" value="white" />
    <param name="minRuntimeVersion" value="3.0.40624.0" />
    <param name="autoUpgrade" value="true" />
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" 
          style="text-decoration:none">
          
      <img src="http://go.microsoft.com/fwlink/?LinkId=108181" 
        alt="Get Microsoft Silverlight" style="border-style:none"/>
    </a>
     </object>
     
     <iframe id="_sl_historyFrame" 
       style="visibility:hidden;height:0px;width:0px;border:0px">
     </iframe>
    </div>
    </form>
</body>
</html>

另外需要注意的是,“<object>”嵌入 Silverlight 应用程序的“width”和“height”被指定为绝对值,以兼容 Firefox。在 Firefox 中,如果指定相对值(如“100%”),Silverlight 应用程序将不可见。

Web.config 文件中的配置信息是:

<appSettings>
 <add key="ApplicationName" value="A Better Silverlight Configuration Demonstration"/>
 <add key="WCFEndPointAddress" value="https:///HelloService/MyService"/>
 <add key="AnotherWCFEndPointAddress"
  value="https:///AnotherService/MyanotherService"/>
 <add key="Author" value="Song Li"/>
 <add key="Version" value="1.0.0.0"/>
 <add key="DeploymentTime" value="02/01/2010"/>
 <add key="CopyRight" value="The Code Project Open License (CPOL)"/>
 <add key="OtherSilverlightApplicationInfo"
  value="Whatever needed to send to Silverlight application @ deployment time"/>
</appSettings>

WCF 服务的接口非常简单。它只定义了一个“OperationContract”,该接口将一个 Dictionary 类型对象返回给 Silverlight 调用者。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace SilverlightBetterConfigurationWeb
{
    [ServiceContract]
    public interface ISilverlightConfiguration
    {
        [OperationContract]
        IDictionary<string, string> GetConfiguration();
    }
}

上述接口的实现位于“SilverlightConfiguration.svc.cs”文件中。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Collections.Specialized;
using System.ServiceModel;
using System.Configuration;
using System.Text;

namespace SilverlightBetterConfigurationWeb
{
    public class SilverlightConfiguration : ISilverlightConfiguration
    {
        public IDictionary<string, string> GetConfiguration()
        {
            Dictionary<string, string> configuration = 
                               new Dictionary<string, string>();
 
            NameValueCollection appSettings = ConfigurationManager.AppSettings;
            for (int Idex = 0; Idex < appSettings.Count; Idex ++)
            {
                configuration.Add(appSettings.GetKey(Idex), appSettings[Idex]);
            }
 
            return configuration;
        }
    }
}

GetConfiguration”方法从 Web.config 读取配置信息,并将其传递给 Silverlight 应用程序。

通过调用 WCF 服务在 Silverlight 应用程序中获取配置数据

在 Silverlight 应用程序中,我创建了一个名为“WCFServiceFactory”的类,以使调用 WCF 服务的代码更清晰。

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.ServiceModel;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightBetterConfiguration
{
    public class WCFServiceFactory
    {
        public SilverlightConfiguration.ISilverlightConfiguration 
               iConfigurationService
        {
            get
            {
                BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
                EndpointAddress endpointAddress = 
                    new EndpointAddress(new Uri(Application.Current.Host.Source, 
                        "/SilverlightConfiguration.svc").AbsoluteUri);
 
                return new 
                  ChannelFactory<SilverlightConfiguration.ISilverlightConfiguration>
                  (basicHttpBinding, endpointAddress).CreateChannel();
            }
        }
    }
}

需要注意的是,只使用了 WCF 服务的“相对路径”来创建“EndpointAddress”。在本例中,“相对路径”就是实现 WCF 服务的文件的名称,即“SilverlightConfiguration.svc”。这意味着,无论 ASP.NET 宿主应用程序部署在哪里,我们都不需要对 Silverlight 应用程序或 WCF 服务进行任何更改。

与《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》类似,配置信息从“App.xaml.cs”文件中获取,并存储在 App 类中一个全局可访问的变量 DeploymentConfigurations 中。

public IDictionary<string, string> DeploymentConfigurations;

private void Application_Startup(object sender, StartupEventArgs e)
{
 SilverlightConfiguration.ISilverlightConfiguration iConfigurationService = 
  (new WCFServiceFactory()).iConfigurationService;
 
 AsyncCallback aSyncCallBack = delegate(IAsyncResult result)
 {
    try
    {
        DeploymentConfigurations =
            ((SilverlightConfiguration.ISilverlightConfiguration)
              result.AsyncState).EndGetConfiguration(result);
    }
    catch (Exception ex)
    {
        Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show(ex.Message));
        return;
    }
 };
 
 iConfigurationService.BeginGetConfiguration(aSyncCallBack, iConfigurationService);
 
 this.RootVisual = new MainPage();
}

运行应用程序

至此,我们已经完成了大部分演示代码的开发。其余工作与我们在《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》中所见的情况完全相同。将“SilverlightBetterConfigurationWeb”设置为启动项目,并将 Default.aspx 设置为起始页,然后就可以调试运行该应用程序了。下图显示了应用程序在 Firefox 中运行的情况。

Run Application

单击“显示配置信息”按钮,Web.config 文件中配置的所有信息都显示在 DataGrid 中。单击“从配置中获取应用程序名称”按钮,将弹出一个消息框,显示应用程序名称:“一个更好的 Silverlight 配置演示”。

关注点

与之前的文章《使用 ASP.NET 的 Web.config 文件配置 Silverlight 3 应用程序》相比,这里介绍的方法解决了两个问题。

  1. 传递到 Silverlight 的信息不再对用户浏览器中的宿主“ASPX”页面中的任何人可见,因此这是一种更安全的方法。
  2. 使用 `=` 和逗号等特殊字符不再是问题。

除了解决这两个问题之外,本文介绍的方法由于 WCF 服务内置的安全功能(禁止任何跨域访问并强制在 Web 浏览器和 Web 服务器之间使用“HTTPS”),因此更加安全。

在研究这个主题的过程中,我在网上做了一些搜索。我发现我们需要在宿主 ASP.NET 页面中设置 Silverlight 对象的绝对大小才能使其在 Firefox 中可见。我们可能需要进一步确认这一点,但至少在我的计算机上的 Firefox 中,Silverlight 应用程序显示出来了,并且工作正常。

历史

这是本文的第一个修订版。

© . All rights reserved.