Feeds:
Posts
Comments

Archive for the ‘WCF’ Category

In the normal case when we want to consume a WCF service, we need to create proxy at client side. To create proxy, service must expose metadata endpoint.

Let us assume we want to call the service using channel without creating proxy or adding the service reference. We need to follow the below steps

Step 1

Put all the DataContract or ServiceContract in a separate DLL or class library. Add the reference of System.ServiceModel in class library. And create the service contract as below,

ServiceWithoutProxy.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
 
 
namespace ServiceContractDll

  [ServiceContract] 
    public  interface ServiceWithoutProxy 
  { 
     [OperationContract] 
      string GetData(int value); 
   }
}
Assume we have created a service library called ServiceContractDll

Step 2

Create a WCF Service application and implement the service contract created in step 1. For that add the reference of project created in step 1 in WCF service application.

Service1.svc.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ServiceContractDll; 
 
 namespace WcfService1

   public class Service1 : ServiceWithoutProxy  
   { 
      public string GetData(int value) 
        { 
            return string.Format(“You entered: {0}”, value); 
        } 
   }
}
Add the EndPoint in config file.

<services>
  
<service name =”WcfService1.Service1″ >
    
<endpoint address =”” binding =”basicHttpBinding” contract =”ServiceContractDll.ServiceWithoutProxy”/>        
           <host> 
               <baseAddresses> 
                   <add baseAddress =”http://localhost:8181/Service1.svc”/
                </baseAddresses> 
         </host> 
   </service>      
</services>

In above config file

ServiceContractDll.ServiceWithoutProxy is name of the service contract exposed.
There is no metadata exchange endpoint in the config file.

Step 3

Create the client. We are creating a console client to consume the service with channel or without creating proxy. So follow the below steps

Do not add the service reference.
Add the reference of System.ServiceModel.
Add the reference of class library created in step1.

Now we need to Create a ChannelFactory

ChannelFactory<ServiceWithoutProxy> factory = null;

Create a binding of the type exposed by service

BasicHttpBinding binding = new BasicHttpBinding();

Create EndPoint address

EndPointAddress address = new EndPointAddress(“http://localhost:4684/Service1.svc“);

Pass Binding and EndPoint address to ChannelFactory

factory = new ChannelFactory<ServiceWithoutProxy>(binding,address)

Now create the channel as below ,

ServiceWithoutProxy channel = factory.CreateChannel();

Call the service method on this channel as below ,

string returnmessage = channel.GetData(9);

 Thanks,

Prashant

Read Full Post »

When i first started using WCF RIA services,  I had a very limited knowledge of WCF . So for many days i didn’t bother whats happening behind the scene, how RIA is using WCF  internally etc. Then one day when i learned WCF, it forced me to explore how it is getting used in WCF RIA 🙂

To help you better understand how RIA Services uses WCF, in the following section I walkthrough what happens under the covers when a user creates a simple DomainService and then communicated with it.

1. ‘Add new DomainService Class’

Lets assume an application developer opens up the ‘Add new Domain Service Class’ item template and adds a new Domain Service.

The item template, besides producing a skeletal Domain Service Class, adds the right assembly references and registers an Http modules in the Web.Config. By default it registers an httpModule for Cassini (for Visual Studio F5 experience) and one for IIS, as shown below.

<?xml version="1.0"?>
<configuration>

  <system.web>
    <httpModules>
      <add name="DomainServiceModule" 
type="System.Web.Ria.Services.DomainServiceHttpModule, 
System.Web.Ria" />
    </httpModules>
    <compilation debug="true" targetFramework="4.0" /> 
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="DomainServiceModule" preCondition="managedHandler"
type="System.Web.Ria.Services.DomainServiceHttpModule, 
System.Web.Ria" />
    </modules>
    <validation validateIntegratedModeConfiguration="false" />
  </system.webServer>
 
 

2. Domain Service Code

The developer then goes ahead and adds Business logic to his DomainService.The methods exposed via the DomainService can be broken into two broad categories –

CRUD operations – Query, Update, Named Update and Delete operations. These operations follow the RIA Services prescriptive guideline and rely on the RIA Services framework. This is added functionality that RIA Services introduces on top of WCF and is not available to Core WCF Services.

Service Operation/ Invoke Operations – These are [Invoke] operation in the RIA Services terminology and Service Operations in WCF terminology. These methods are independent of the RIA Services concept of ChangeSet (ChangeSet applies only to the CRUD operations above) and are ‘Online/Direct’ methods that communicate with the Server immediately when invoked.

Below is the code for the OrganizationService DomainService we use in our canonical RIA Services walkthrough.

namespace HRApp.Web
{
    [EnableClientAccess()]
    public class OrganizationService : 
        LinqToEntitiesDomainService<AdventureWorks_DataEntities>
    {
        #region CRUD    
        public IQueryable<Employee> GetEmployee(){…}        
        public void InsertEmployee(Employee employee) {…}        
        public void UpdateEmployee(Employee currentEmployee) {…}        
        public void DeleteEmployee(Employee employee) {…}
        public IQueryable<Employee> GetSalariedEmployee(){…}
        [RequiresAuthentication()]
        public void ApproveSabbatical(Employee current) {…}   
        #endregion

       #region ServiceOperations
        public string Echo(string msg) {…}
        public DateTime GetServerDateTime(){…}
       #endregion
    }
}

3. WCF Channel on Client

The RIA Services Framework on the Client contains a WebDomainClient:DomainClient whose purpose is to help the SL client communicate with a WCF service represention of the Domain Service. The WebomainClient uses a WCF Client Chanel for this cummunication.

The Channel is created by using WCF’s ChannelFactory and by passing to it a WCF Service Contract that was generated from the Domain Service (more on the contract creation later). The ChanelFactory creates a WCF client proxy based on the supplied contract. The generated proxy takes care of communication/(de)serialization between Client and Server.

The RIA Services DomainContext utilizes the WebDomainClient for Client-Server communication and the context itself is WCF agnostic.

4. Dynamic .SVC generation

By default DomainServices do not have a physical .SVC file generated for them at Design Time.

However each DomainService has a virtual .SVC associated with it. The .SVC represents the WCF Service that services requests for that particular DomainService. For a given DomainService the path to its .SVC can be determined using the following convention:

[SilverlightApplicationBaseURI] + [DomainServiceFullName].svc (With all “.” replaced by ““)

So HRApp.Web.OrganizationService is exposed as – http://[ApplicationBaseURI]/HRApp-Web-OrganizationService.svc

At RunTime when the first request (within a particular Application Domain) is made for a DomainService’s .SVC file , the registered httpModules intercept the call and RIA Services writes out an in memory .SVC file on the fly.

Below is what the dynamically generated svc file looks like for the OrganizationService defined above –

<%@ ServiceHost Service=”HRApp.Web.OrganizationService” 
Factory=”System.Web.Ria.DomainServiceHostFactory”
%>
 

The .SVC refers to the DomainService Type and a ServiceHostFactory. The default RIA Services  HostFactory instantiates the default RIA Services ServiceHost, which in turn is responsible for extracting the WCF Service Contract from the DomainService (See the ‘Generating a WCF Contract’ paragraph below for more details) and also for hosting the service.

A request for the DomainService .SVC in any folder under the Web Application root is redirected to [WebAppRoot]/Services/[DomainService].svc using ASP.net URL rewriting. The service is thus accessible under any folder in the WebApp. Hence even if a .XAP is moved around under the hosting Web App Root, the Silverlight App’s relative reference to the DomainService is not broken. 

NOTE – If a physical .svc file with the right file name (as per convention) is present in the ~/Services folder, that is used to define the Service Contract and no virtual .SVC file is generated.

5. Generating the WCF Contract:

Each WCF service needs to have a ServiceDescription and one or more ContractDescriptions for it.

ServiceHosts are responsible for extracting descriptions from a service and hosting the service. The standard ServiceHost in WCF produces descriptions based on WCF attributes such as [ServiceContract] and [OperationContract]. In RIA Services we provide a custom ServiceHost which does this based on a RIA Service Attributes and Conventions.

Here is how DomainService operations are mapped to the WCF Contract:

Query operations –

Each Query operation shows up as a ServiceOperation in the WCF Contract, but with its signature modified.

The ServiceHost creates an operation description for each query operation. The return type is changed to QueryResult<T> such that it can return additional information such as count. It also adds a QueryOperationBehavior which through a custom operation Invoker takes care of applying cache policies, validating parameters and composing queries.

Insert, Update, Delete operations –

For all CUD operations the ServiceHost generates one top-level SubmitChanges operation description. Again, it adds a custom behavior which injects a custom operation invoker. The signature of SubmitChanges is ChangeSet SubmitChanges(ChangeSet changeSet). The returned ChangeSet contains auto-generated values from the server.

Invoke Operations –

Invoke Operations are the RIA Services equivalent of WCF ServiceOperations. All Invoke Operations show up in the WCF Contract as Service Operations.

For the OrganizationService Domain Service we had defined earlier, below is what the WCF Contract looks like to the “Add Service Reference” dialog –

image

Attached to this post is also the full generated WCF Contract for the OrganizationService (the file was produced by doing an Add Service Reference to the Domain Service’s WCF endpoint)

6. Default Endpoints:

The RIA Services ServiceHost creates the following endpoints by default – 

a) For Silverlight Client: SOAP w/binary endpoint. Address = “binary”, Binding = CustomBinding consisting of HttpTransportBindingElement and BinaryMessageEncodingBindingElement.

b) For AJAX Client: JSON REST endpoint. Address = “”, Binding = WebHttpBinding w/JSON as the format.

c) For other clients : SOAP w/XML endpoint. Address = “soap”, Binding = BasicHttpBinding consisting of HttpTransportBindingElement and TextMessageEncodingBindingElement.

For more information refer to http://blogs.msdn.com/b/saurabh/archive/2009/11/23/understanding-the-wcf-in-wcf-ria-services.aspx

There might be some breaking changes that can be found here –code.msdn.microsoft.com/…/ProjectReleases.aspx

Also, here is a sample that demos the use of WCF extensibility by RIA services and runs on the latest bits –

code.msdn.microsoft.com/…/ProjectReleases.aspx

 Thanks,

Prashant

Read Full Post »