代码之家  ›  专栏  ›  技术社区  ›  Lasse Espeholt

在Silverlight 3中保留状态

  •  0
  • Lasse Espeholt  · 技术社区  · 16 年前

    我正在开发一个Silverlight3应用程序,我想用提供的.dll或SOAP连接到Web服务。但是.dll不适合Silverlight,所以我不能这样做。而且,由于跨域问题,我无法访问SOAP服务(我不托管它,所以clientpolicy XML不会这样做)。

    因此,我的解决方案是在我自己的域中启用WCF的WebService中包含.dll,并让Silverlight应用程序调用WebService。这是可行的。

    现在我的问题是:由我的WebService引用的.dll提供的客户端有一个.connect()方法,因此我必须保存对象的状态。但我能做到吗?可能不是因为Silverlight不支持wshttpbinding。我知道我可以访问ASP会话变量,但我也可以在浏览器外这样做吗?对于我的问题,我只能找到一个解决方案,那就是在ASP会话中保存用户名/密码,并在每个方法中调用.connect()方法。但这确实是一个糟糕的解决方案。

    更好的主意?


    我想我没有说清楚,为此我道歉。我的英语正是造成这种情况的主要原因。

    我有:

    我的Silverlight应用程序在网站上运行,并且不在浏览器中

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

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

    我的wcf webservice在我的应用程序和跨域webservice之间提供了一个层,因为没有策略文件不能添加跨域webservice。

    我的WebService如下(抽象地):

    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 回复  |  直到 15 年前
        1
  •  0
  •   Bryant    15 年前

    我不是100%确定我理解这个问题,但我确实有一个类似的情况,我的工作,这里是我们如何处理的。

    1. 第三方网络服务 存储所有数据。
    2. 我们创建的WCF中间层处理所有 与WebService的交互。
    3. Silverlight客户端层 连接到我们的WCF服务。

    对于身份验证,我们在WCF服务上有一个身份验证方法,该方法随后调用WebService并传递我们从Silverlight提交的凭据。然后,WebService使用一个身份验证令牌进行响应,我们将该令牌设置为Silverlight请求上的cookie。因此,将来来自Silverlight的所有调用都将包含这个令牌,我们在每次调用WebService时都会传递这个令牌。

    显然,您不想将用户名和密码设置为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;
        }
    }
    

    当然,您将存储客户机服务,而不是日期时间。现在,这种方法还有一些问题需要解决。

    1. 超时-您需要某种方法来超时那些不活动的会话,并从客户机列表中清除它们。
    2. 我不确定这是不是一个超级安全的方式来做事情。如果有人得到了你的guid,他们就可以访问你的员工。但是,我不知道会发生什么,但我不是安全专家。

    就是现在,如果你有问题,请告诉我。

        2
  •  0
  •   Shawn Mclean    16 年前

    如果您的dll不是根据Silverlight 3运行时生成的,则不能从Silverlight项目引用它。要求客户端在该运行时重新生成DLL。

    Silverlight在运行需要完全信任的代码时是严格的。如果Silverlight应用程序不知道DLL在哪个运行时中,它将根本不接受它或对它进行任何调用。

        3
  •  0
  •   Doug Ferguson    15 年前

    更新:

    您可以标记服务,以便在会话的生命周期内将服务对象保留在内存中。

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

    这将使跨域客户端在调用之间保持初始化状态。

    原始答案:

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

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