2009-10-24 47 views
0

我正在開發一個Silverlight 3應用程序,我想通過提供的.dll或SOAP連接到webservice。但.dll不適合Silverlight,所以我不能這樣做。由於跨域問題,我無法訪問SOAP服務(我沒有託管它,因此clientpolicy xml不會這樣做)。在Silverlight中保留狀態3

所以我的解決方案是將.dll包含在我自己的域中啓用WCF的web服務中,並讓Silverlight應用程序調用web服務。這工作。

現在我的問題:從我的web服務引用的.dll提供的客戶端有一個.Connect()方法,所以我必須保存該對象的狀態。但我能做到嗎?嚴格來說不是因爲Silverlight不支持wsHttpBinding。我知道我可以訪問ASP會話變量,但我也可以做到瀏覽器外?我只能找出解決我的問題的一種解決方案,即在ASP Session中保存用戶名/密碼,並在每種方法中調用.Connect()方法。但這真是一個糟糕的解決方案。

更好的主意?


我不認爲我已經說清楚了,我對此表示歉意。我的英語正是這個主要原因。

我:

我它運行在網站上和Silverlight應用程序外的瀏覽器

這是在同一個域中託管

我的WCF服務。

跨域web服務(我不能訪問存儲跨域策略文件)

我的WCF Web服務提供了我的應用程序和跨域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顯然不受支持。

回答

0

我不是100%確定我理解這個問題,但我確實有一些與我合作的情況類似,我們在這裏處理它。

  1. 其中 存儲所有數據的第三方web服務。
  2. 由我們創建的WCF中間層,用於處理與webservice的所有 交互。
  3. Silverlight客戶端層 連接到我們的WCF服務。

對於身份驗證,我們在我們的WCF服務上有一個身份驗證方法,然後調用webservice並傳遞從Silverlight提交的憑據。然後,webservice會使用我們在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; 
    } 
} 

當然,而不是日期時間,您將存儲您的客戶端服務。現在,您仍然需要解決這個方法的一些問題。

  1. 超時 - 您需要某種方式來暫停未激活的會話,並從客戶端列表中清除它們。
  2. 我不確定這是否是一種超安全的方式來做事情。如果有人得到你的指導,那麼他們可以訪問你的員工。但是,我不明白這是如何發生的,但我不是安全專家。

這就是現在,如果你有問題讓我知道。

+0

hm,很好的解決方案。我的Silverlight應用程序和跨域web服務之間有一個WCF web服務。但是,我如何維護一個對象從調用我的web服務到另一個? – 2009-10-28 18:23:53

+0

該對象應該使用WCF服務中的服務引用來定義。然後通過WCF服務引用將該對象共享給Silverlight。然後,您會將該對象從Silverlight傳遞到WCF到Web服務。 – Bryant 2009-10-28 21:58:47

+0

我對最初發布的內容做了一些補充,希望他們能夠清理我想要的內容:) MVH – 2009-10-29 15:38:25

0

如果您的dll不是針對silverlight 3運行時構建的,那麼您無法從Silverlight項目中引用它。請您的客戶在該運行時重建該DLL。

對於需要完全信任的代碼,Silverlight是嚴格的。如果silverlight應用程序不知道dll所在的運行時間,它將不會接受它或根本不進行任何調用。

+0

我知道,我不能問他們:/因此,我已經在我自己的域中提出了一個引用.dll的web服務:) – 2009-10-24 22:43:47

+0

.dll也調用web服務,以便給我同樣的問題就像現在我想的那樣。 – 2009-10-24 22:49:23

0

更新:

您可以標記爲您服務,保持服務對象在內存中的會話的生活。

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

這應該讓您的跨域客戶端在兩次調用之間初始化。

原來的答覆:

Silverlight對象保持通話之間活着,所以你可以在內存中保持狀態。

如果要在Silverlight應用程序運行之間存儲狀態,可以將狀態序列化到客戶端計算機上的獨立存儲並在Silverlight應用程序啓動時將其讀回。

+0

我對最初的帖子做了一些補充,希望他們能夠清理我想要的東西:)致以最大的問候 – 2009-10-29 15:39:24

+0

它不能按預期工作。 SessionMode = Required也是必需的,這對basicHttpBinding不起作用。 – 2009-11-01 19:45:02