在Silverlight 3中保留状态

时间:2009-10-24 22:22:18

标签: silverlight session silverlight-3.0 web-services state

我正在开发一个Silverlight 3应用程序,我希望通过提供的.dll或SOAP连接到Web服务。但.dll不适合Silverlight,所以我不能这样做。由于跨域问题,我无法访问SOAP服务(我不托管它,因此clientpolicy xml不会这样做。)

所以我的解决方案是在我自己的域中的WCF启用的webservice中包含.dll,并让Silverlight应用程序调用webservice。这很有效。

现在我的问题:我的webservice引用的.dll提供的客户端有一个.Connect()方法,所以我必须保存对象的状态。但我能这样做吗? Proberly并不是因为Silverlight不支持wsHttpBinding。我知道我可以访问ASP Session变量,但是我也可以在浏览器外执行此操作吗?我只能找出问题的一个解决方案,即在ASP Session中保存用户名/密码,并在每个方法中调用.Connect()方法。但这确实是一个糟糕的解决方案。

更好的想法?


我认为我没有说清楚,我为此道歉。我的英语是正确的原因。

我有:

我的Silverlight应用程序在网站和浏览器外运行

我的WCF服务托管在同一个域中。

跨域web服务(我无法访问存储跨域策略文件)

我的WCF网络服务在我的应用和跨域网络服务之间提供了一个层,因为您无法在没有策略文件的情况下添加跨域网络服务。

我的网络服务看起来像这样(以抽象的方式):

class MyWebService
{
   CrossDomainWebServiceClient client = new CrossDomainWebServiceClient();

   public void Connect(string username, string password)
   {
      client.Connect(username, password);
   }

   public object Foo()
   {
      //GetEmployees() do only work if I'm connected
      return client.GetEmployees(); 
   }
}

Foo()方法不起作用,因为它是每次调用的会话而不是每个实例的会话。我想要这个工作。因此,需要保留客户端对象以进行下一次调用。 Session.required在Silverlight中不起作用,因为显然不支持wsHttpBinding。

3 个答案:

答案 0 :(得分:0)

如果您的dll不是针对silverlight 3运行时构建的,那么您无法从silverlight项目中引用它。请求您的客户在该运行时重建dll。

Silverlight在运行需要完全信任的代码时非常严格。如果silverlight应用程序不知道dll所处的运行时间,它将不会接受它或对它进行任何调用。

答案 1 :(得分:0)

我不是百分百肯定我理解这个问题,但我确实有一些类似的情况与我合作,这就是我们如何处理它。

  1. 第三方网络服务 存储所有数据。
  2. 由我们创建的WCF中间层来处理所有 与webservice的交互。
  3. Silverlight客户端层 连接到我们的WCF服务。
  4. 对于身份验证,我们在WCF服务上有一个身份验证方法,然后调用Web服务并传递我们从Silverlight传递的凭据。然后,Web服务使用我们在Silverlight请求上设置为cookie的身份验证令牌进行响应。因此,Silverlight未来的所有调用都将包含我们在每次调用Web服务时传递的令牌。

    显然,您不希望将用户名和密码设置为cookie。但希望您可以从Web服务中获取某种cookie或令牌,然后您可以在将来的请求中使用它们。

    更新了答案

    根据您更新的规格,听起来您需要缓存服务客户端。您可以尝试使用Custom WCF Instance Contexts,但这是一个简单的方法。

    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class ProxyService
    {
        private static Dictionary<Guid, DateTime> clients = new Dictionary<Guid, DateTime>();
    
        public ProxyService()
        {
    
        }
    
        [OperationContract]
        public void Login()
        {
            Guid id = Guid.NewGuid();
            // perform your login here
            clients.Add(id, DateTime.Now); // store your client instead of a date
            SetCookie(id);
        }
    
        [OperationContract]
        public DateTime Foo()
        {
            var id = ReadCookie();
            if (clients.ContainsKey(id))
            {
                return clients[id];
            }
            return DateTime.MinValue;
        }
    
        private void SetCookie(Guid id)
        {
            var cookie = new HttpCookie("id", id.ToString());
            cookie.Expires = DateTime.Now.AddMinutes(10);
            HttpContext.Current.Response.AppendCookie(cookie);
        }
    
        private Guid ReadCookie()
        {
            var cookie = HttpContext.Current.Request.Cookies.Get("id");
            if (cookie != null)
            {
                cookie.Expires = DateTime.Now.AddMinutes(10);
                return new Guid(cookie.Value);
            }
            return Guid.Empty;
        }
    }
    

    当然,您可以存储客户服务,而不是DateTime。现在,这种方法存在一些问题,您仍需要解决这些问题。

    1. 超时 - 您需要某种方法来暂停未激活的会话并从客户列表中清除它们。
    2. 我不确定这是否是一种超级安全的做事方式。如果有人拿到你的指导,那么他们就可以访问你的员工。但是,我不知道会发生这种情况,但我不是安全专家。
    3. 现在就是这样,如果您有任何疑问,请告诉我。

答案 2 :(得分:0)

更新

您可以将服务标记为在会话期间将服务对象保留在内存中。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
class MyWebService{   
    CrossDomainWebServiceClient client = new CrossDomainWebServiceClient();   

这应该使您的跨域客户端在调用之间保持初始化。

原始答案:

Silverlight对象在调用之间保持活动状态,因此您可以在内存中维护状态。

如果要在Silverlight应用程序的运行之间存储状态,可以在客户端计算机上将状态序列化为独立存储,并在Silverlight应用程序启动时将其读回。