0

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

所以我的解决方案是在我自己的域中的启用 WCF 的 Web 服务中包含 .dll,并让 Silverlight 应用程序调用 Web 服务。这行得通。

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

更好的想法?


我认为我没有说清楚,对此我深表歉意。我的英语是正确的主要原因。

我有:

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

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

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

我的 WCF Web 服务在我的应用程序和跨域 Web 服务之间提供了一个层,因为没有策略文件就无法添加跨域 Web 服务。

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

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。

4

3 回答 3

0

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

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

于 2009-10-24T22:27:26.707 回答
0

我不是 100% 确定我理解了这个问题,但我确实遇到了一些类似的情况,这是我们处理它的方式。

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

对于身份验证,我们在 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. 我不确定这是否是一种超级安全的做事方式。如果有人得到了您的指导,那么他们就可以访问您的员工。但是,我不知道这会如何发生,但我不是安全专家。

暂时就是这样,如果有问题请告诉我。

于 2009-10-27T18:51:12.657 回答
0

更新:

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

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

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

原答案:

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

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

于 2009-10-28T19:21:50.937 回答