views:

406

answers:

3

Hi,

I'm developing a Silverlight 3 Application which I want to connect to a webservice with a provided .dll or with SOAP. But the .dll is not suited for Silverlight so I can not do that. And I can't access the SOAP service because of cross-domain issues (I do not host it so a clientpolicy xml will not do).

So my solution is the include the .dll in a WCF enabled webservice in my own domain and let the Silverlight application call the webservice. This works.

Now to my problem: The client provided from the .dll referenced by my webservice has a .Connect() method so I have to save the state of the object. But can I do that? Proberly not because Silverlight is not supporting wsHttpBinding. I know I can access ASP Session variables but can I also do that out-of-browser? I can only figure out one solution to my problem and that is saving username/password in ASP Session and call the .Connect() method in each method. But that is really a bad solution.

Better ideas?


I don't think I have made myself clear and I apologise about that. My english is properly the main cause for that.

I have:

My Silverlight app which runs on a website and out-of-browser

My WCF Service which is hosted in the same domain.

A cross-domain webservice (I can't get access to store a cross domain policy file)

My WCF webservice provides a layer between my app and the cross-domain webservice because you can't add cross domain webservices without the policy file.

My webservice looks like this (in a abstract way):

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(); 
   }
}

The Foo() method do not work because it is session per call and not session per instance. I want this to work. So the client object need to be preserved for the next call. Session.required do not work in Silverlight because wsHttpBinding apparently is not supported.

A: 

If your dll is not built against the silverlight 3 runtime then you cannot reference it from your silverlight project. Ask your client to rebuild the dll in that runtime.

Silverlight is strict when it comes to running codes that would require full trust. If the silverlight application does not know what runtime the dll is in, it will not accept it or make any call to it at all.

Shawn Mclean
I know, I can't ask them :/ It is therefore I have made a webservice in my own domain which reference the .dll :)
lasseespeholt
The .dll is also calling a webservice so that would give me the same problem as now I guess.
lasseespeholt
A: 

I'm not 100% sure I understand the question, but I do have a somewhat similar situation that I work with and here is how we handle it.

  1. Third party webservice which stores all the data.
  2. WCF middle tier created by us to handle all the interactions with webservice.
  3. Silverlight client tier which connects to our WCF service.

For authentication we have an authentication method on our WCF service which then calls the webservice and passes the credentials we handed in from Silverlight. The webservice then responds with an authentication token which we set as a cookie on the Silverlight request. So then all the future calls from Silverlight will include this token which we pass with each call to the webservice.

Obviously you wouldn't want to set the username and password as a cookie. But hopefully you can get some kind of cookie or token back from the webservice which you can then use in future requests.

Updated Answer

Based on your updated specs, it sounds like you'll need to cache the service clients. You could try to get fancy with Custom WCF Instance Contexts, but here is a simple approach.

[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;
    }
}

Of course, instead of a DateTime you would store your client service. Now there are a few issues with this approach that you would still need to solve.

  1. Timeouts - you would need some way to timeout the sessions that aren't active and clear them from the list of clients.
  2. I'm not sure if this is a super secure way to do things. If someone got your guid then they could access your employees. However, I don't see how this would happen, but I'm not a security expert.

That is it for now, if you have questions let me know.

Bryant
hhm, fine solutions. I have a WCF webservice between my silverlight app and the cross domain webservice. But how do I maintain a object from call to my webservice to another?
lasseespeholt
The object should be defined using the service reference in the WCF service. Then the object should be shared to Silverlight through the WCF service reference. You would then pass the object from Silverlight to WCF to the webservice.
Bryant
I have made some additions to my initially post and I hope they will clearify what I want :) MVH
lasseespeholt
Just updated to address your additions.
Bryant
Looks like something I can go further with :) I can't test the code were I am currently, but can you tell me whether the static Dictionary will be preserved between the calls? Because if I can't, I can't see it work.
lasseespeholt
Yes, a static variable will persist between calls until the application closes, which should be okay since by that time it would have timed out.
Bryant
A: 

Update:

You can mark your service to retain the service object in memory for the life of the session.

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

This should keep your cross-domain client initialized between calls.

Original answer:

The Silverlight object stays alive between calls so you can maintain state in memory.

If you want to store state between runs of the Silverlight application you can serialize state to isolated storage on the client computer and read it back in when the Silverlight application starts up.

Doug Ferguson
I have made some additions to my initially post and I hope they will clearify what I want :) Best regards
lasseespeholt
It does not work as expected. SessionMode=Required is also required and that will not work with basicHttpBinding.
lasseespeholt