Solving Caching problem of IE for WCF REST service

Objective

This article will explain; how to solve the caching problem in IE while making call to for REST enabled WCF service. Client might be a SILVERLIGHT client or AJAX client.

Background

Read my other articles on WCF REST service for better understanding of this article.

Is REST service and a web page is same?

Theory says YES, these two are almost the same entity exist on web. Calling a REST service is exactly the same as of browsing the web page on the web.

REST is architecture to create service not a specification. And it works on the HTTP verbs.

REST stands for Representational state transfer where each operation in a service is uniquely identified. Each operation has their, own unique URI and can be accessed via this URL all across the web. Each operation in service definition is attributed with the HTTP verbs they are going to work with. So if URL of a REST service is browsed from the browser, it will return response from the service in form of either JSON or XML base on the service definition.

So, the below link can be browsed in browser.

http://localhost:80/Service1.Svc/GetName?deptId=9

Temporary Internet Files and History Settings

There are four options for cache settings in Internet Explorer


 

Every Time I visit the Web Page

On returning of the page which has been viewed previously, IE checks on the server whether viewed page has been changed. If viewed page has been changed, IE will display the new changed page else it will display the cached page.

Note: If this setting is selected in browser there is no need of handle the caching through code. There is no caching for this option.

Every Time I Start Internet Explorer

In this option IE will download the newer version from the server only when browser got reopened or refreshed [F5]. Else each time IE will show the cached page.

Automatically

In this option IE download the new page from the server based on certain algorithm. This is default setting of the browser.

Never

In this option IE never go to server to download the page. Always browser shows the cached page.

Bottom Line is, since
browsing web page and REST Service call is exactly the same so browser setting applies to calling REST service also. So caching problem does apply to REST service call also.

How to solve caching problem?

There are two ways to solve the caching problem of REST service call.

  1. Through work around
  2. Through JQuery

Through Work Around

Let us suppose service is

[WebGet(ResponseFormat = WebMessageFormat.Json)]

[OperationContract]


List<string> GetNames(string deptId);

 

Service is hosted somewhere and service is being called by,

AJAX cleint

$.getJSON(‘Service1.svc/ GetNames,

{ deptId: ids },

function(data,status){}

 

Silver Light Client

HttpClient proxyClient = new
HttpClient();

proxyClient.TransportSettings.Credentials = CredentialCache.DefaultCredentials;

string targetURI = string.Format(“/Service1.svc?deptId={0}”,deptId);

HttpResponseMessage response = proxyClient.Get(targetURI);

 

Now, if service is being called with the deptId=9; then URL of calling service will be

http://localhost:80/Service1.Svc/GetName?deptId=9

And a response will get cached at the client browser.

Problem Statement

Now consider and scenario, when for the deptId =9 database has been changed at the service side. If browser is set as the default (Automatic) and for the next service call with same dept id, browser will call the URL http://localhost:80/Service1.Svc/GetName?deptId=9 , and response for this URL has been cached at the browser, so at the client side changed database won’t be reflected.

Solution

This is a work around solution; just add an extra parameter of type DateTime in service and each time at calling the service pass current date time from the client. So each time there will be a unique URL and that won’t be cached. So each time browser will download the latest response from the server regardless of the browser setting.

Modify service as

[WebGet(ResponseFormat = WebMessageFormat.Json)]

[OperationContract]


List<string> GetNames(string currentDateTime, string deptId);

 

So now at time of calling the service just pass the current date time and it will modify the Service URL each time. So browser will get the response from the service each time.

http://localhost:80/Service1.Svc/GetName?currentDateTime=12-12-2009:10.00.00,deptId=9

After 1 sec the service call will get modify with the URL and this is new URL .

http://localhost:80/Service1.Svc/GetName?currentDateTime=12-12-2009:10.00.01,deptId=9

Through JQuery

This solution is only applicable for the AJAX client.

  1. Call $.ajaxSetup({ cache: false }); before making the service call.
  2. Call $.ajaxSetup({ cache: true }); after making the service call.
$.ajaxSetup({ cache: false });

$.getJSON(‘Service1.svc/ GetNames,

{ deptId: ids },

function(data,status){}

$.ajaxSetup({ cache: true });


Conclusion

This article explained about working with cache problem in IE while making call to REST enabled WCF service. Thanks for reading.

NTLM and Windows Authentication on WCF service

Objective

This document will explain various combinations of IIS and WCF Ntlm/Windows authentication settings.

What is difference between NTLM and WINDOWS authentication in WCF?

Windows authentication = authentication in NTLM + authentication in Active Directory

NTLM authentication = authentication in only NTLM

IIS configuration

For all scenario IIS is configured for Windows authentication. What I mean is Windows Authentication is enabled and all other authentication is disabled. Navigate to below path to open ApplicationHost.Config file of IIS.

C:\Windows\System32\inetsrv\config\applicationHost.config

Binding used in WCF service

For all scenario basicHttpBinding being used for WCF service.

Scenario #1

Default setting for IIS Applicationhost.Config is

<windowsAuthentication enabled=false>

<providers>

<add value=Negotiate />
<add value=NTLM />
</providers>
</windowsAuthentication>

If IIS APP.Config file is having default setting, then we can have any authentication for WCF service corresponding IIS configured; WCF service will run as expected without any error.

Note: SharePoint is running as expected

Browsers Behavior with default settings

  1. IE 7.0 is not asking for authentication
  2. Fire Fox 3.5.6 is asking user to authenticate
  3. Safari 4.0.4 is asking user to authenticate

Scenario #2

If IIS Applicationhost.Config File setting has been modified as below, where forcefully Windows authentication is enabled for Kerberos then we have to modify service with Windows authentication.

<windowsAuthentication enabled=true><providers>
<add value=Negotiate />
<!–<add value=”NTLM” />–>
</providers>
</windowsAuthentication>

WCF configuration setting for Windows authentication should be

<basicHttpBinding>

<binding name=BasicHttpBinding>
<security mode =TransportCredentialOnly>
<transport lientCredentialType =Windows/>
</security>
</binding>
</basicHttpBinding>

 

Note: SharePoint is running as expected

Browsers Behavior with default settings

  1. IE 7.0 is not asking for authentication
  2. Fire Fox 3.5.6 is asking user to authenticate
  3. Safari 4.0.4 is asking user to authenticate

Scenario #3

If IIS Applicationhost.Config File setting has been modified as below, where forcefully Windows authentication is enabled for NTLM

<windowsAuthentication enabled=true>

<providers>

<!–<add value=”Negotiate” />–>

<add value=NTLM />
</providers>
</windowsAuthentication>

 And we go with Windows authentication for the service, we will get below error

<basicHttpBinding>

<binding name=BasicHttpBinding>

<security mode =TransportCredentialOnly>

<transport clientCredentialType =Windows/>

</security>

</binding>

</basicHttpBinding>

So to remove above error, WCF configuration setting for should be modified for the NTLM authentication.

<basicHttpBinding>

<binding name=BasicHttpBinding>

<security mode =TransportCredentialOnly>

<transport clientCredentialType =Ntlm/>

</security>

</binding>

</basicHttpBinding>

 

Note: SharePoint is running as expected

Browsers Behavior with default settings

  1. IE 7.0 is not asking for authentication
  2. Fire Fox 3.5.6 is asking user to authenticate
  3. Safari 4.0.4 is asking user to authenticate

Summary

Sl No

IIS (Applicationhost.Config ) setting

WCF (Web.config) setting

1 Default Ntlm and Windows Binding behavior
2 Windowauthentication = true and Value = Negotiate Windows authenticated Bidding behavior
3 Windowauthentication = true and Value = Ntlm Ntlm authenticated Binding behavior

So,

  1. If we have ApplicationHost.Config of IIS configured as default, we can have either of Ntlm or Windows authentications for WCF service.
  2. If we have ApplicationHost.Config of IIS configured as Ntlm, we can have only Ntlm authentication for WCF service.

If we have ApplicationHost.Config of IIS configured as Windows, we can have only Windows authentication for WCF service.

Step by Step walkthrough to host WCF service in Windows Azure

Objective

This article will give step by step walkthrough of hosting a WCF service in windows azure.

Note: Before reading through this walkthrough see this http://djoncloud.cloudapp.net/DjService.svc . We are going to host this service in this walkthrough.

Prerequisite

VS 2010 Beta

Windows AZURE SDK should be installed on the system.

Step 1

Open Visual Studio 2010 as an administrator. Select File -> New -> Cloud Service. Click on Windows Azure cloud service template. Give name of the cloud service. After creating the cloud service select the type of role. There are many roles to choose from. For our purpose, we will choose ASP.Net Web Role. After creating ; Now examine the solution explorer. There should be 2 projects. Called WebRole1 and CloudServices1. These names may different basis of the name you given at time of creation of cloud service project in step1.

Step 2

Creating the WCF Service

Right click on WebRole1 project and add new item then select WCF service from the WEB project template.

Modify contract and service implementation as per you. For my purpose , I am making it simple service as below.

Contract

 [ServiceContract]
public interface IDjService
 {
[OperationContract]
string GetMyName(string name);
}

 Service Implementation

public class DjService : IDjService{
public string GetMyName(string name){
return “helllo “ + name + “to my service hosted in Azure”;
} }

 Change the Binding to basicHttpBinding. Make sure to do this.

Note : make sure you have set WebRole1 as startup project .

Step 3

Running on Local Development Fabric (Press F5)

Run the application. This will run on the local development fabric. When we install azure SDK, local development fabric got installed. And when we run the cloud service local development fabric get started and host the application. This provides exactly the same environment as of azure in the cloud. This local development fabric could be used to debug the application before hosting into the cloud.

Running the application on local development fabric

See the URL in address bar of browser, in my case this is

http://localhost:49863/DjService.svc

Step 4

Publishing to cloud (azure)

Right Click on Cloud Service 1 project and select Publish. And publish to azure. See my other articles for details.

Now when you open the URL after publishing , you will get the same page as output you got on the local development fabric. And now you successfully hotsed in cloud.

WCF service hosted in Azure

http://djoncloud.cloudapp.net/DjService.svc

Step 4

Consuming the service hosted in Windows Azure

Create a console application to consume the service. There is a known bug with Azure where a proxy cannot be created from the Azure hosted service. So to as a workaround to create proxy

  1. While adding service reference first adds URL of the service hosted on local development fabric. Copy the URL from Step 3 and right click on Console application and select Add service reference. In service URL paste the URL from step 3.

Call the service hosted in local development fabric like below,

using testingWcfAzureclient.ServiceReference1;
namespace testingWcfAzureclient
{class Program{
static void Main(string[] args)
{
DjServiceClient proxy = new DjServiceClient();
Console.WriteLine(proxy.GetMyName(“Dhananjay “));
Console.Read();
}}}

Output


Open the App.config and modify the address to address of service in azure.

<client><endpoint
address=http://djoncloud.cloudapp.net/DjService.svc
binding=basicHttpBinding
bindingConfiguration=BasicHttpBinding_IDjServicecontract=ServiceReference1.IDjServicename=BasicHttpBinding_IDjService /></client>

Again run the application and you will get the same output.