Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Tuesday, November 22, 2011

Calling WCF From Silverlight Without Using Service Reference

Calling WCF From Silverlight Without Using Service Reference
In this article I will demonstrate how to call WCF service without using the Service Reference. Practical reasons of doing this as a developing is allowing us to have more control over our calls to WCF.

Basically I will introduce two ways of doing this;

1. Using the ChannelFactory

2. Using the ClientBase

To start calling WCF service to your Silverlight application first we have to copy the ServiceContract and DataContract codes to our silverlight projects.

namespace Demo.Wcf.Services
{
[System.ServiceModel.ServiceContract()]
public interface PersonService
{

[System.ServiceModel.OperationContract(AsyncPattern = true)]
IAsyncResult BeginGetPerson(int no, AsyncCallback callback, object state);

Person EndGetPerson(IAsyncResult result);

}

[System.Runtime.Serialization.DataContract()]
public class Person
{
private int _No;
[System.Runtime.Serialization.DataMember()]
public int No
{
get { return _No; }
set { }
}

private string _FirstName;
[System.Runtime.Serialization.DataMember()]
public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; }
}

private string _LastName;
[System.Runtime.Serialization.DataMember()]
public string LastName
{
get { return _LastName; }
set { _LastName = value; }
}

private DateTime _BirthDate;
[System.Runtime.Serialization.DataMember()]
public DateTime BirthDate
{
get { return _BirthDate; }
set { _BirthDate = value; }
}

public Person(int no)
{
_No = no;
}
}
}
First thing to note from the above code is the namespace should be the same namespace as the service definition. Secondly, the service methods will be defined using the Async pattern. Primary reason for doing this is Silverlght 2 only supports async operations to WCF calls. To define the service methods using async pattern is to define methods with Begin and End prefix (e.g. BeginGetPerson, EndGetPerson) and set the attribute OperationContract AsyncPattern parameter to true. This will instruct the runtime to interprete the methods prefixed by Begin and End.

Now we come to the most interesting part how to call the service. as mention we will implement this in wo ways

Using ChannelFactory

protected void Page_Loaded(object sender, RoutedEventArgs e)
{
PersonService svc = new ChannelFactory(
new BasicHttpBinding(),
new EndpointAddress("http://localhost:9902/PersonService.svc")).CreateChannel();
svc.BeginGetPerson(0,
delegate(IAsyncResult result)
{
Person p = ((PersonService)result.AsyncState).EndGetPerson(result);
this.Dispatcher.BeginInvoke(
delegate()
{
txtName.Text = p.FirstName;
}
);
},
svc);
}
As you can see from the above code that it is pretty straight forward similar on the how the ChannelFactory is being used by the .NET Framework. However important thing to note was to use the Dispatcher when assigning values to the control properties this is to avoid cross-thread errors.

Using the ClientBase

To use the ClientBase we need to create a class that will inherit the ClientBase class and for the sake of my implementation I suggest to create an event argument class as well. This is necessary because our implementatio will be using the event base pattern.


namespace Demo.Wcf.Services
{
public class PersonServiceEventArgs : EventArgs
{
private Person _Result;

public Person Result
{
get { return _Result; }
}

public PersonServiceEventArgs(Person result)
{
_Result = result;
}
}

public class PersonServiceClient : ClientBase
{
public event EventHandler GetPersonCompleted;

public PersonServiceClient(Binding binding, EndpointAddress endpoint) : base(binding, endpoint)
{

}

public void GetPersonAsync(int no)
{
IAsyncResult result = Channel.BeginGetPerson(no, GetPersonCallback, no);
}

private void GetPersonCallback(IAsyncResult result)
{
Person p = Channel.EndGetPerson(result);
if (GetPersonCompleted != null)
GetPersonCompleted(this, new PersonServiceEventArgs(p));
}

protected override PersonService CreateChannel()
{
return base.CreateChannel();
}
}
}
The above example is also straightforward is a sense that we implemented an event that will response when the call from WCF has been completed and the result will be retrieved from the event argument class that we created. Now to call this from your Silverlight is pretty simple also.

protected void Page_Loaded(object sender, RoutedEventArgs e)
{

PersonServiceClient proxy = new PersonServiceClient(new BasicHttpBinding(), new EndpointAddress("http://localhost:9902/PersonService.svc"));
proxy.GetPersonCompleted += delegate(object source, PersonServiceEventArgs args)
{
this.Dispatcher.BeginInvoke(
delegate()
{
txtName.Text = args.Result.FirstName;
}
);
};

proxy.GetPersonAsync(0);
}

Monday, July 5, 2010

WCF Windows Authentication

When the We want to get the Windows identity inside the WCF that was hosted inside the IIS we need to do the some configuaration inside the service configuration.We will always get the Windows identiy inside the WCF service when we are working on the development server .Since the develpment server is always runs inside the integrated web server (ie inbuild webserver from VS2005).


So inorder to get the Windows identity  first and for most  we need to add the following config


   <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

This  is to enable the asp.net Compatibility then only we can acess the HTTP Context that contains the User Identity


The follwing binding which will give the Current user identity
<bindings>
    <basicHttpBinding>
      <binding name ="BasicHttpBindingConfig">       
        <security mode="TransportCredentialOnly">
          <transport clientCredentialType="Windows" />
        </security>
      </binding>
    </basicHttpBinding>
</bindings>

we need to add this Binding inside the service where we need to access the windows identity like

<service behaviorConfiguration="SecurityConfigurationServiceBehavior" name="SecurityConfigurationService">
<endpoint address="" binding="basicHttpBinding" contract="ISecurityConfigurationService" behaviorConfiguration="SilverlightFaultBehavior"                  bindingConfiguration ="BasicHttpBindingConfig" >
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
       
</service>

After this configuration we have to ensue that no more end points are configured.

We need to enable some settings inside the IIS  to get the Windows Identity i.e  enable is Windows integrated  options