WCF 4.0 Features: Part #1

WCF 4 comes with many of new features for better developer experience. There is high integration with workflow service. Making WCF REST service more developer friendly and Configuration less WCF service. In short WCF 4 tries to address common scenario easily and at the same time gives us more options to communicate in between service and client.

Below are the few of new features of WCF 4.0

1. Dynamic Service and End Point discovery

2. Intermediate Routing Pattern ( Generic Routing Services)

3. Discovery announcement

4. Simplified Configuration

5. Protocol bridging and Fault tolerance

6. Default End Points.

7. .svc-less activation of REST services or making REST URI nice.

8. Default Protocol Mapping

9. Help page enabled for WCF Rest service and many more.

In this article we will see in detail three exciting features of WCF 4.0. and in further articles we will see the other features

In this article we are going to see

1. EndPoint Discovery

2. Default EndPoints

3. Help page enabled for WCF REST Service

Problem

People say; you need to know only ABC of a service to expose End Point of that service. And client or service consumer needs to know only End Point to consume the service. But wait for a while here, and think; what if? Binding need to change at the service side from basic to WS over HTTP, This is very basic change but to accommodate this client has to update the service again. And this is very much error prone. It is very tedious task to update client about all the basic frequent change at the service side. To solve this issue, there should be some mechanism and that is called End Point Discovery or Dynamic Service.

In absolute technical words

WCF 4.0 supports WS –Discovery standard or protocol.

WS-Discovery Standard

1. This is a multicast protocol that issues SOAP message over UDP,

2. WS-Discovery is a Standard that defines a lightweight discovery mechanism for discovering services based on multicast messages. It enables a service to send a Hello announcement message when it is initialized and a Bye message when is removed from the network.

3. Client or consumer can discover services by multicasting a Probe message to which a service can reply with a ProbeMatch message containing the information necessary to contact the service.

4. Client or consumer can find services that have changed endpoint by issuing a Resolve message to which respond with a ResolveMatchmessage.

So, we can say WS –Discovery is a UDP based multicast message exchange. This message receives End Point information from Service and uses this as discovery information. Client uses discovery information to discover the available service on the network.

WCF Service Discovery API

WCF provides, WCF Discovery API for dynamic publish and discovery of web service using WS –Discovery protocol. This API helps service to publish them and helps client to find service on the network.

Modes

clip_image002

Managed Mode

1. In managed mode there is a centralized server called a discovery proxy that services use to publish themselves and clients use to retrieve information about available services.

2. When a new service starts up it sends an announcement message to the discovery proxy.

3. The discovery proxy saves information about each available service to storage.

4. When a client must search for a service it sends a Probe request to the discovery proxy and it determines whether any of the services that have been published match the request.

5. If there are matches the discovery proxy sends a ProbeMatch response back to the client.

6. The client can then contact the service directly using the service information returned from the proxy.

Ad-Hoc Mode

1. There is no centralized server.

2. Service announcements and client requests are sent in a multicast fashion.

3. If a service is configured to send out a Hello announcement on start up, it sends it out over a well-known, multicast address using the UDP protocol.

4. Therefore, clients have to actively listen for these announcements and process them accordingly.

5. When a client issues a Probe request for a service it is also sent over the network using a multicast protocol.

6. Each service that receives the request determines whether it matches the criteria in the Probe request and responds directly to the client with a ProbeMatch message if the service matches the criteria specified in the Probe request.

Sample

In this sample, we will create a very basic service and at the client side, first client will discover the service in Ad-Hoc mode and then consume that.

To run and go through this sample, you need Visual Studio 2010 Beta.

To make a service discoverable, a ServiceDiscoveryBehavior must be added to the service host and a discovery endpoint must be added to specify where to listen for and send discovery message

Step1

Open VS2010. Create a new project by choosing WCF Service Application Project template.

Step 2

Delete all the code which is generated by Visual studio. After deleting Contract and Service Implantation is as follows.

IService1.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService1
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetMessage(string  msg);
}
}

Service1.cs


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

namespace WcfService1
{
public class Service1 : IService1
{
public string GetMessage(string msg)
{
return msg;
}

}
}

The above is simple Service Contract and implantation of that.

Step3

Open Web.Config file. And modify the System.ServiceModel. Add the code which in red rectangle below.

Web.Config


<system.serviceModel>
<services>
<service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
<endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1">

<identity>
<dns value="localhost"/>
</identity>
</endpoint>

<endpoint name ="udpDiscovery" kind ="udpDiscoveryEndpoint" />

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfService1.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>

<serviceDiscovery />

</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

Explanation of Config file

1. One new End Point is being added.

2. Kind of newly added End Point is udpDiscoveryEndpoint.

3. This End Point will be used to discover the service.

4. ServiceDiscovery behavior is also get added.

Step 4

Press F5 to run the service. Service will get hosted in ASP.Net web server.

clip_image006

Step 5

Add a new console project in solution.

Step 6

Add Reference of System.ServiceModel.Discovery.dll in console project.

clip_image007

Step 7

Add namespace using System.ServiceModel.Discovery;

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;
using System.ServiceModel;
using System.ServiceModel.Discovery;

namespace ConsoleApplication1

{
class Program

{

static void Main(string[] args)

{

DiscoveryClient discoverclient = new DiscoveryClient(new UdpDiscoveryEndpoint());

FindResponse response = discoverclient.Find(new FindCriteria(typeof(IService1)));

EndpointAddress address = response.Endpoints[0].Address;

Service1Client client = new Service1Client(new  WSHttpBinding(), address);

string str= client.GetMessage("Hello WCF 4 ");

Console.WriteLine(str);

Console.ReadKey(true);

}

}
}

Explanation of the code

1. We are making object of DiscoveryClient class. This class is user to discover available service.

2. In constructor of this class, we are passing UdpDiscoveryEndPoint of the service.

3. Then we are calling Find method with contract name as argument to get FindResponse.

4. Now FindResponse variable having all the available address for contract passed in Find method.

5. We are creating the client proxy and passing discovered address as argument.

6. Calling the service operation on the client proxy.

Output

clip_image009

Default End Points and Protocol mapping

For a normal developer like me, had a great challenge working with WCF 3.x was configuration of End Points in config file. Developer had to add endpoints to setup a WCF service. In WCF 4, Defualt End Point is associated with the service, if we don’t configure any WCF endpoint.

Walkthrough

To see how Default EndPoint works follow the steps below,

Step1

Create a WCF service application.

Let us create two service contracts

IService1.cs


[ServiceContract]
public interface IService1
{

[OperationContract]
string GetData();
}

IService2.cs


[ServiceContract]
public interface IService2
{
[OperationContract]
string GetMessage();
}

Now let us implement the service as below,


public class Service1 : IService1, IService2
{
public string GetData()
{
return "Hello From Iservice1 ";

}

public string GetMessage()
{
return " Hello From Iservice2";
}

Step 2

Now we will host this service in a console application, Create a new console application project.

Add reference of WCF service application project and also add reference of System.serviceModel in the console application project.

Note: There is no App.Config associated with console application.

clip_image011

Here, we are registering two base addresses with the servicehost. One for http binding and other for nettcp binding.

Now we don’t have any configuration for the service EndPoint . ServiceHost will create default EndPoints .

Now ServiceHost will configure EndPoints for two base addresses


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

ServiceHost host = new ServiceHost(typeof(WcfService1.Service1),
new Uri("<a href="http://localhost:8080/service">http://localhost:8080/service</a>"),
new Uri("net.tcp://localhost:8081/service"));

host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
Console.WriteLine("Address: " +  se.Address.ToString() +
"  Binding: " + se.Binding.Name +
" Contract :"+ se.Contract.Name);
}

Console.ReadKey(true);

}
}
}

Output would be

clip_image013

The default protocol mapping for default EndPoints are mapped as below,

clip_image015

Since HTTP is mapped with basicHttpBinding , so we got the default EndPoint with basicHttpBinding.

Default EndPoint will only get created if there is not a single Endpoint configured. If we add any single EndPoint then all then there won’t be any default EndPoint get configured.

If we add one EndPoint as below,

clip_image017

We added one service EndPoint and now the output we would get for below code ad below,


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

ServiceHost host = new ServiceHost(typeof(WcfService1.Service1),
new Uri("<a href="http://localhost:8080/service">http://localhost:8080/service</a>"),
new Uri("net.tcp://localhost:8081/service"));

host.AddServiceEndpoint(typeof(IService1),
new WSHttpBinding(),
"myBinding");

host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
Console.WriteLine("Address: " +  se.Address.ToString() +
"  Binding: " + se.Binding.Name +
" Contract :"+ se.Contract.Name);
}

Console.ReadKey(true);

}
}
}

Output

clip_image019

Now we see that if we configure EndPoint then WCF does not support default Endpoints.

If we closely look at the output that by default WCF maps protocol to binding as below.

clip_image020

So if we are not configuring any EndPoint , then for http type base address in default EndPoint created by WCF will have basicHttpBinding.

If we see the above mapping , by default http type is mapped to basicHttpBinding , net.tcp type is mapped to netTcpBinding and so on.

If we want to change this, we can change this default mapping

clip_image022

Now when we do the above change in the Web.Config file then when we do not define any EndPoint then for HTTP type base address, WCF will create the EndPoint with wsHttpBinding.

So to understand more, what I am talking about

1. Create a WCF Service application

2. Create a Service contract as below


[ServiceContract]
public interface IService1
{

[OperationContract]
string GetData();
}

3. Implement the Service as below


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

namespace WcfService1
{

public class Service1 : IService1
{
public string GetData()
{
return "Hello From Iservice1 ";

}

}
}

4. Now we will host this service in a console application, Create a new console application project. Add reference of WCF service application project and also add reference of System.serviceModel in the console application project.

5. Right click on the console project and add app.config file to console project. Right the below configuration in App.Config


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<protocolMapping >
<add  scheme ="http" binding ="wsHttpBinding" bindingConfiguration ="" />
</protocolMapping>
</system.serviceModel>
</configuration>

6. Now write the below code to fetch the default Endpoint created by WCF


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

ServiceHost host = new ServiceHost(typeof(WcfService1.Service1),
new Uri("<a href="http://localhost:8080/service">http://localhost:8080/service</a>"));

host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
Console.WriteLine("Address: " +  se.Address.ToString() +
"  Binding: " + se.Binding.Name +
" Contract :"+ se.Contract.Name);
}

Console.ReadKey(true);

}
}
}

And output we would get is

clip_image024

So we can see that how we modified the default mapping using Protocol mapping in System.ServiceModel

Enabling Help page for REST Service in WCF 4.0

WCF 4.0 provides us feature to eanable Help page on WCF REST Service.

Walkthrough

In this walkthrough we will see,

1. How to create a REST based service?

2. How to host a REST based service in Console application?

3. How to enable Help page for REST Service?

Follow the steps as below,

Step1

Create a New project. Select Console application as project type.

clip_image026

Step 2

Add a new project to same solution. Choose the project type as class library.

clip_image028

Step 3

Add below references in both projects console and service library

System.ServiceModel;

System.ServiceModel.Description;

System.ServiceModel.Web;

clip_image029

If you are not able to get System.ServiceModel.Web dll by default , when you are adding as Add Reference in your console application project and class library project , then follow the below steps

1. Right click on your console application project or class library project

2. Select properties from context menu

3. From Application tab, if you see by default .NET Framework 4 Client profile is selected. Change that to .NET Framework 4.0. So your target framework should be .NET Framework 4.0.

clip_image030

Now you should able to see all the dll when you add service reference in project.

Step 4

In this step, I will create contract of service

1. Open the Contract (Class Library project).

2. Delete Class1.

3. Right click and add a new item then select Interface from Code tab.

clip_image032

4. Make Interface as public and put ServiceContract attribute.

5. Declare two operation contracts. Make one attributed with WebGet and another attributed with Web Invoke.

IService.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace Contracts
{
[ServiceContract]
public  interface IService
{
[OperationContract]
[WebGet]
string GetMessage(string inputMessage);

[OperationContract]
[WebInvoke]
string PostMessage(string inputMessage);
}
}

Step 5

In this step, I will implement the contract in Service file. To do so,

1. Right click and add a class in Console application.

clip_image034

2. Give any name; I am giving name here Service of the class.

3. Implement the interface (Contract IService) in this class.

Service.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Contracts;

namespace SelfHostedRESTService
{
public  class Service :IService
{
public string GetMessage(string inputMessage)
{
return "Calling Get for you " + inputMessage;
}

public string PostMessage(string inputMessage)
{
return "Calling Post for you " + inputMessage;
}
}
}

Step 6

In this step, I will host the service in a console application. So to do so

1. Open Program.cs

2. Create instanced of WebServieceHostFactory

clip_image036

3. Add a service end point

clip_image038

4. Add service host behavior with help page enabled

clip_image040

As we know, REST service used webHttpBindding. And we are enabling Help page here.

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using Contracts;

namespace SelfHostedRESTService
{
class Program
{
static void Main(string[] args)
{

WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("<a href="http://localhost:8000">http://localhost:8000</a>"));
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");

host.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });
host.Open();
Console.WriteLine("Service is up and running");
Console.WriteLine("Press enter to quit ");
Console.ReadLine();
host.Close();
}
}
}

Step 7

Just press F5 to run the service.

clip_image042

Now once service is up and running, I can test,

To test the Help page, just type

http://localhost:8000/help

clip_image044

When you click on Get or Post link you will get below detail help.

clip_image046

In next article we will see some other features of WCF 4.0

Want to develop for Social Networking using ASP.Net 4.0? Then grab the book ASP.Net 4.0 Social Networking authored by Atul Gupta

clip_image001

If you want to read some real hands on experience on LINQ, C#4.0, AJAX, MVP pattern etc. then this book is for you. This book is authored by three industry veteran and they have put all their real time experience here.

You can order for the book from here

Few highlights about book

· Create a full-featured, enterprise-grade social network using ASP.NET 4.0

· Learn key new ASP.NET and .NET Framework concepts like Managed Extensibility Framework (MEF), Entity Framework 4.0, LINQ, AJAX, C# 4.0, ASP.NET Routing,n-tier architectures, and MVP in a practical, hands-on way.

· Build friends lists, messaging systems, user profiles, blogs, forums, groups, and more

· A practical guide full of step by step explanations, interesting examples, and practical advice

About the Authors

Atul Gupta

Principal Architect – Microsoft Technology Center, Infosys Technologies

With over 14 years of experience working on Microsoft technologies, Atul is currently a Principal Architect at Infosys’ Microsoft Technology Center. His expertise spans User Interface technologies, and he currently focuses on Windows Presentation Foundation (WPF) and Silverlight technologies. He has also authored papers for industry publications and websites. Being actively involved in professional Microsoft online communities and developer forums, Atul has received MVP award for six years in a row.

Andrew Siemer

Enterprise architect at OTX Research

Andrew Siemer is currently the enterprise architect at OTX Research. He has worked as a software engineer, enterprise architect, trainer, and author since 1998 when he got out of the Army. Andrew has consulted with many companies on the topics of e-commerce, social networking, and business systems. To name a few, he has worked with eUniverse (AllYouCanInk.com), PointVantage (MyInks.com), Callaway Golf (CallawayConnect.com), Guidance Software (GuidanceSoftware.com), and Intermix Media (Grab.com, AmericanIdol.com, FoxSports.com, FlowGo.com). In addition to his daily duties he also offers various classes in .NET, C#, and other web technologies to local students in his area as well as blogging in his *free* time.

Sudhanshu Hate

Senior Architect, Microsoft Technology Center, Infosys Technologies

With 11 years of experience, Sudhanshu is currently focusing on Windows Communication and Workflow Foundation technologies from the .Net 3.5 and 4.0 stack. Previously, Sudhanshu has led solution architecture and development teams on Legacy Modernization and Business Intelligence and was also instrumental in taking Infosys’ Catalytic IT solutions to customers in EMEA.

Windows Azure for Developers Task 14 : Working with Windows Azure BLOB storage

There are plenty of articles and blog posts about theoretical concept of BLOB are already available. So I am not going to rediscover the wheel. What could you expect from this post is a code walkthrough to perform

1. Insert Image in BLOB

2. Delete Image from BLOB

3. Fetch Image from BLOB

4. Create a container in BLOB

5. Ensure Container is available or not

Before I go to walkthrough one simple introduction of BLOB is, “BLOB is a type of storage in Windows Azure allows you to work with big size files

I may discuss full theoretical concept of BLOB in some other post but about scope of this post, I have already mentioned.

So let us start coding

1. Open visual studio as administrator

2. Create New project

3. Select CLOUD project from Cloud tab.

4. Add a web Role

Follow the below steps ,

Add Connection string for BLOB storage

To add a connection string you need to add it as setting of the Web Role. To add a setting right click on the Role and select Properties

clip_image001

Select Settings tab and add a new setting. To add a new setting you will have to click Add Setting at top. Give a name to setting. Here I am giving name DataConnectionString . From drop down select Connection String as a type

clip_image003

Once you have given name and type to new setting click on extreme right to provide value to the setting. I am going to use local storage. If you are planning to use Azure Storage then you will have to provide

1. Azure storage account credential

2. BLOB endpoint.

3. For local development fabric selects first option.

clip_image004

Add Container Name

To add Container name, essentially you need to add one more setting.

clip_image006

I am giving name as ContainerName, type as String and value as mygallery

There are few rules you need to keep in mind while giving name of the container

1. Must start with a number or letter or dash.

2. Must contain only lower case

3. Must be minimum 3 in length and maximum 63 characters in length.

Create a BLOB Utility class

I am going to create a Utility class. This class will contain all the basic functions related to BLOB storage.

I am going to have four basic functions

1. Get the Container

2. Ensure Container exist

3. Upload a file

4. Delete a file

5. Retrieve a file

Right click on WebRole project and add a class. I am giving name of the class BLOBUtility.

clip_image008

Make sure you have added the below namespaces and put the class a static.

Microsoft.WindowsAzure;
Microsoft.WindowsAzure.ServiceRuntime;
Microsoft.WindowsAzure.StorageClient
;

Basic structure of your class should look like below image

clip_image010

Write a function to get the Container

In BLOBUtility static class write a static function called GetContainer(). This function will return CloudBLOBContainer .

clip_image012

In above function,

First I am getting storage account. Make sure that you are passing correct Connection String Name. If you would have noticed, I created a connection string of name “DataConnectionString “in previous steps. So as input, I am passing DataConnectionString.

Second task I am doing is creating a BLOB Client.

Third task I am doing is getting the reference of container by passing the container name. Again if you would have noticed in previous steps I created a container of name “ContainerName

Write a function to ensure Container exist

In BLOBUtility static class write a static function called EnsureContainer(). This function will not return anything.

clip_image014

In above function,

First I am getting the Container and if container does not exist, creating it. I am setting the Public Access permission to Container.

Write a function to save Image

In static class BLOBUtility write a static function called InsertImage(). This function will not return anything

clip_image016

In above function, you need to pass metadata associated with the file as input parameter. A very important point worth noting here is that make sure you are passing an ID for sure as input parameter. At time of calling pass unique GUID as ID. Essentially there are three parts in above function.

1. Creating Metadata from input parameters.

2. Adding Metadata to the BLOB

3. Uploading Byte Array to the BLOB.

Write a function to Delete Image

In static class BLOBUtility write a static function called DeleteImage(). This function will not return anything

clip_image018

In above function as input parameter pass URI of image to delete. Using image URI get the BLOB reference and delete image file.

Once DeleteImage function is ready your BLOB Utility class is ready to use.

BLOBUtility.cs


using System;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.Collections.Specialized;

namespace WebRole1
{
public static  class BLOBUtility
{

public static CloudBlobContainer GetContainer()
{
try
{
//var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
var account = CloudStorageAccount.Parse
(RoleEnvironment.GetConfigurationSettingValue
("DataConnectionString"));

var client = account.CreateCloudBlobClient();
var blobReference = client.GetContainerReference(RoleEnvironment.GetConfigurationSettingValue("ContainerName"));
return blobReference;
}
catch (Exception ex)
{
return null;
}
}

public static void EnsureContainer()
{
var container = GetContainer();
container.CreateIfNotExist();
var permission = container.GetPermissions();
permission.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permission);
}

public static void InsertImage(string Id, string name, string fileName, string contentType, byte[] imageData)
{
var blob = GetContainer().GetBlobReference(name);
blob.Properties.ContentType = contentType;
var metaData = new NameValueCollection();
metaData["Id"] = Id;
metaData["FileName"] = fileName;
metaData["ImageName"] = name;
blob.Metadata.Add(metaData);
blob.UploadByteArray(imageData);

}

public static void DeleteImage(string imageURI)
{
var blob = GetContainer().GetBlobReference(imageURI);
blob.DeleteIfExists();
}
}
}

Design aspx page

Default.aspx


<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebRole1._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
<asp:Label ID="Label1" runat="server" Text="Select Image to Upload"></asp:Label> <br />
<asp:Label ID="Label2" runat="server" Text="Give File Name "></asp:Label>
<asp:TextBox ID="txtFileName" runat="server" Width="114px"></asp:TextBox> <br />
<asp:FileUpload ID="FileUpload1" runat="server" />
</p>
<asp:Button ID="btnUpload" runat="server" Text="Upload Image" Width="209px"
onclick="btnUpload_Click" />
<div>
<asp:ListView ID="images" runat="server" onitemdatabound="OnBlobDataBound">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</LayoutTemplate>
<EmptyDataTemplate>
<h2>No Data Available</h2>
</EmptyDataTemplate>
<ItemTemplate>
<div>
<ul style="width:40em;float:left;clear:left" >
<asp:Repeater ID="blobMetadata" runat="server">
<ItemTemplate>
<li><%# Eval("Name") %><span><%# Eval("Value") %></span></li>
</ItemTemplate>
</asp:Repeater>
<li>
<asp:LinkButton ID="deleteBlob"
OnClientClick="return confirm('Delete image?');"
CommandName="Delete"
CommandArgument='<%# Eval("Uri")%>'
runat="server" Text="Delete" oncommand="OnDeleteImage" />

</ul>
<img src="<%# Eval("Uri") %>" alt="<%# Eval("Uri") %>" style="float:left"/>
</div>
</ItemTemplate>
</asp:ListView>
</div>
</asp:Content>

I have put on the aspx page

1. One textbox

2. One File Upload Control

3. One List view with repeater control

I am binding List box with all the Images from BLOB

clip_image020

In above function I am setting as Data Source of repeater control Meta data values from the BLOB.

To bind the image control with Image from BLOB

clip_image022

For your reference full source code is as below,

Default.aspx.cs


using System;
using System.Linq;
using System.Web.UI.WebControls;
using Microsoft.WindowsAzure.StorageClient;

namespace WebRole1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BLOBUtility.EnsureContainer();

}

this.LoadImage();
}

private void LoadImage()
{

images.DataSource = BLOBUtility.GetContainer().ListBlobs(new BlobRequestOptions()
{
UseFlatBlobListing = true,
BlobListingDetails = BlobListingDetails.All
});
images.DataBind();

}

protected void btnUpload_Click(object sender, EventArgs e)
{
BLOBUtility.InsertImage(Guid.NewGuid().ToString(),txtFileName.Text,FileUpload1.FileName , FileUpload1.PostedFile.ContentType, FileUpload1.FileBytes);
LoadImage();
}

protected void OnDeleteImage(object sender, CommandEventArgs e)
{

if (e.CommandName == "Delete")
{

BLOBUtility.DeleteImage((string)e.CommandArgument);
}
LoadImage();

}
protected void OnBlobDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
var metadataRepeater = e.Item.FindControl("blobMetadata") as Repeater;
var blob = ((ListViewDataItem)(e.Item)).DataItem as CloudBlob;
if (blob != null)
{
if (blob.SnapshotTime.HasValue)
{
var delBtn = e.Item.FindControl("deleteBlob") as LinkButton;
if (delBtn != null) delBtn.Text = "Delete Snapshot";

}

if (metadataRepeater != null)
{
//bind to metadata
metadataRepeater.DataSource = from key in blob.Metadata.AllKeys
select new
{
Name = key,
Value = blob.Metadata[key]
};
metadataRepeater.DataBind();
}
}
}
}
}
}

Press F5 to run application on local development fabric interacting with BLOB storage.

Windows Azure for Developers Task 13: SetConfigurationSettingPublisher needs to be called before FromConfiguration Setting can be used error [Other Solution]

I would like to thank Neil Mackenzie for this post. His input on below exception [as comment in my previous post ] is content of this post .

clip_image001

In my previous post, I suggested solution of above exception , and I got a comment from one of my reader that there is an easier way to solve above exception as well. So I decided to make a post on the other way of solution as well.

Very first I won’t say solution discussed in previous post is harder than solution discussed in this post or vice versa.

Usually we read connection string as,

clip_image003

DataConnectionString is name of the connection string in setting of WebRole.

To avoid above exception read connection string as

clip_image005

So essentially,

1. First get the configuration setting value

2. Parse that

I hope this post would be useful to you in getting rid of above exception.

30 day free trial for SQL Azure/Windows Azure without Credit Card

clip_image002 clip_image004

I am excited to share with you people that,

Now you can see your code is running as Web/Worker role in Azure hosted service, your application is performing CRUD operation on database resides SQL Azure and many other more stuff and that also without using your valuable CREDIT CARD

Now you can get free Azure account for 30 days on trial basis and registration does not require your credit card information as well.

Just go to,

www.sqlazure.com/getstarted

And register yourself. You can choose second option to get a free trial for 30 days without giving your credit card details.

clip_image006

You can get many learning resources from community site

http://www.microsoft.com/en-us/sqlazure/community.aspx

So put your shirt sleeves up and start playing around SQL Azure and Windows Azure with free trial.

Last but not least I would like to thank Cameron T. RogersSenior Product Manager SQL Azure for sharing this information with me . Thanks for your help to community .

Windows Azure for Developers Task 12: SetConfigurationSettingPublisher needs to be called before FromConfiguration Setting can be used error

Have you spent your hours getting rid of below exception ?

clip_image001

I spent. So in this blog post, I am trying to save your time.

Very first let us understand why this error occurs?

Azure application runs in Full IIS model from SDK 1.3 onwards.

In simple English we can say that from SDK 1.3 onwards WebRole.cs and Web Application codes run in different application domain. So if we write or we do have code for Set Configuration setting in WebRole.cs then we are going to get above exception.

How to solve?

1. Make sure you have Diagnostic connection string in settings of Web Role.

clip_image003

2. See if in your Web Role project Global.asax file exist. If it does not exist then right click on the Web Role project and add one.

3. Open Global.asax.cs file and in Application_Strat() add the below code

clip_image005

Bottom line is to get rid of below exception, you need to copy below code in Application_Strat() .

Code to copy


CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
{
var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
configSettingPublisher(connectionString);
}
);

I hope this post may have saved your some time.

Connecting Microsoft Access to SQL Azure

I have already posted on many level 100 developers articles on SQL Azure. You can read them here. I thought if my SQL Azure blog post series does not have a post on “Connecting SQL Azure to Microsoft Access “then it cannot be called as complete post series. So I gave a try and came up with this blog post. Before you start reading this step by step walkthrough, I request you to first have a read on some of previous blog posts on SQL Azure here

As my other SQL Azure post, I am going to connect School Database again. To connect Microsoft Access with SQL Azure School database follow the steps as below.

1. Open Microsoft Access and create a blank Database.

clip_image002

2. Click on the Create button in left to create a blank database.

clip_image003

3. From top select External Data and ODBC Database option

clip_image005

4. Select the second radio button.

clip_image007

5. New panel will come to select Database server name.

clip_image008

6. Click on New and you will pop up with a new panel. To connect with SQL Azure select SQL Server Native Client 10.0

clip_image009

7. Click on Advanced option. Here you need to give ODBC connection string to SQL Azure Database. Login to SQL Azure portal and copy paste ODBC connection string here

To get connection string, select Database and at right in the property you will get Connection string.

clip_image010

Copy ODBC connection string from here,

clip_image011

Copy paste ODBC connection string in this panel after selecting advanced option.

clip_image012

8. Click on ok and give a name to connection. I am giving name abc.

clip_image013

Click next and select Finish. You will prompt with new panel as below

9. Uncheck Use Trusted Connection check box. Provide password and click OK

clip_image014

10. Oh My God and here you are, you have all the tables from SQL Azure Database listed to select in Microsoft Access.

clip_image015

Few points you need to cross check

1. See the Firewall rules of SQL Azure Database server.

2. Edit the Firewall rule range to cover IP address of your client machine.

3. Check SQL Server 2008 R2 native client is installed on your client machine.

4. While copying ODBC Connection string, you have changed the password.

Thanks , I hope this post was useful.