U2U Blog

for developers and other creative minds

AZURE Roadshow at HOWEST - demos

Last week, I did a presentation on Windows Azure at HOWEST, University College West Flanders. As promised, my hands-on-labs of this session.

1. A file archive application to upload/download files into a database in the cloud.  This application consists out of a webpage (UploadFile.aspx) to upload files into a SQL Azure database, and a REST service to dowload your files as a stream. You can dowload the sources at : CodeArchiveService.zip

To get you up and running in the develoment fabric, first create a local database in SQL Server and add a table called CodeArchive. Modify the config files to point to your database.

CREATE TABLE [dbo].[ZipArchive](
[CodeName] [varchar](200) PRIMARY KEY CLUSTERED  NOT NULL,
[CodeBlob] [varbinary](max) NULL)
 

Next, to deploy into the cloud: create a database in SQL Azure, create a login and grant access to your database and create a table called CodeArchive (same as above). Now, change the config files to point to this database.

-- On the master database:
CREATE LOGIN <login> WITH password='<password>'

-- On your database:
CREATE USER <user> FROM LOGIN <login>
EXEC sp_addrolemember 'db_owner', '<user>'
 



2. A photo browser application :

  • Contains a synchronous Upload.aspx (storage right into SQL Azure) and an asynchronous UploadAsync.aspx (blob storage to store the image temporarily + queued messaging to send a message to a background workerrole)
  • Contains a workerrole for thumbnailing the image and saving both the image and the thumbnail  in SQL Azure
  • Contains a Silverlight photo browser app which talks to a WCF service to retrieve it's data (no rocket science here to be focused on Azure stuff as much as possible)

You can dowload the sources at : PhotoBookService.zip

Tables needed (both locally and in SQL Azure):

CREATE TABLE [Photo](
    [PhotoID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    [ThumbNailPhoto] [varbinary](max) NULL,
    [LargePhoto] [varbinary](max) NULL)
 

CREATE TABLE [Comment](
    [PhotoID] [int] NOT NULL,
    [CommentID] [int] IDENTITY(1,1) NOT NULL,
    [Comments] [varchar](1000) NULL,
 CONSTRAINT [PK_Comment_PhotoID_CommentID] PRIMARY KEY CLUSTERED 
(
    [PhotoID] ASC,
    [CommentID] ASC
))

ALTER TABLE [dbo].[Comment]  WITH CHECK ADD  CONSTRAINT [FK_Photo_Comment] FOREIGN KEY([PhotoID])
REFERENCES [dbo].[Photo] ([PhotoID])

ALTER TABLE [dbo].[Comment] CHECK CONSTRAINT [FK_Photo_Comment]

Multiple Silverlight controls in 1 XAP

Basically, when you are creating a website with 2 Silverlight contols, you need to have 2 xap files in your ClientBin folder. It would be better if you could have 1 xap file but you decide which usercontrol you want to see.

A solution could be using InitParams in the object tag in your HTML file:

image

in the app.xaml you write following code:

image

K.

IErrorHandler: A generic Fault Converter (2/2)

My previous post IErrorHandler: A generic Fault Converter (1/2) describes how to build an ErrorHandler for WCF. The challenge is now to write a generic ErrorHander which can be configured to automatically convert exceptions into faults based upon a pre-defined list of converter methods. Converting an exception into a fault is one thing, but we need to be careful that we only return those faults that the operation contract defines (by means of FaultContract attributes)

Lets first focus on the implementation of the converter : we need a delegate definition for a method that takes any Exception as input and that converts this into a Fault. Faults are just classes that have a DataContract attribute (or even without when trusting on POCO support introduced in .NET 3.5 SP1). Since there isn’t any base class for FaultContracts, let’s define the type as generic.

public delegate TFault FaultConverter<TFault>(Exception e);



The converter maintains a Dictionary of exception types as keys and FaultConverter<TFault> delegates as values. We need to be able to add new converter methods and execute the converter method that suits the exception type.

public class ExceptionToFaultConverter
{
  private Dictionary<Type, Delegate> lst = new Dictionary<Type, Delegate>();

  public void AddConverter<TException, TFault>(FaultConverter<TFault> converter)
  {
    lst.Add(typeof(TException), converter);
  }

  public object Convert(Exception ex)
  {
    if (lst.ContainsKey(ex.GetType()))
    {
     return lst[ex.GetType()].DynamicInvoke(ex);
    }

    return null;
  }
}
 
Adding a converter just looks like this :
 
faultConverter.AddConverter<DivideByZeroException, Faulty>(e => new Faulty() { ErrorMessage = e.Message });

 

During ProvideFault(), theFautlConverter will convert the Exception info a fault (if any). Next thing to to is checking if we can return this fault for the current operation.

  public class MyErrorHandler : Attribute, IErrorHandler, IServiceBehavior
  {
    ExceptionToFaultConverter faultConverter =new ExceptionToFaultConverter();

    public MyErrorHandler()
    {
      faultConverter.AddConverter<DivideByZeroException, Faulty>(
        e => new Faulty() { ErrorMessage = e.Message }
        );
    }

    public bool HandleError(Exception error)
    {
      return false;
    }

    public void ProvideFault(Exception error, 
      System.ServiceModel.Channels.MessageVersion version, 
      ref System.ServiceModel.Channels.Message fault)
    {      
      ServiceDescription description = OperationContext.Current.Host.Description;      
      ServiceEndpoint endpoint = description.Endpoints.Find(OperationContext.Current.IncomingMessageHeaders.To);
      
      string operationName =OperationContext.Current.IncomingMessageHeaders.Action.Replace(
        endpoint.Contract.Namespace + endpoint.Contract.Name + "/", "");
      OperationDescription operation =endpoint.Contract.Operations.Find(operationName);

      object faulttype = faultConverter.Convert(error);
      if (faulttype == null)
          return;

      foreach (FaultDescription faultdescription in operation.Faults)
      {
          if (faultdescription.DetailType.IsAssignableFrom(faulttype.GetType()))
          {
              fault = Message.CreateMessage(
                  version,
                  FaultCode.CreateSenderFaultCode(
                          faultdescription.Name, 
                          faultdescription.Namespace),
                  faulttype.ToString(),
                  faulttype,
                  faultdescription.Action);
              break;
          }
      }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, 
      System.ServiceModel.ServiceHostBase serviceHostBase, 
      System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, 
      System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
      System.ServiceModel.ServiceHostBase serviceHostBase)
    {
      foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)
      {
        disp.ErrorHandlers.Add(this);
      }
    }

    public void Validate(ServiceDescription serviceDescription, 
      System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }
  }

MSDN event: Firestarter

For those who wants to be ahead of the game, but do not have time to see events, msdn firestarter is the solution to your problem.

This site offers you free webcasts talking about Microsoft technologies such as:

  •   ASP.NET MVC
  •   Silverlight
  •   Windows 7
  •   …

So when you have time, and next week it is going to rain ( no excuses allowed ), take some time to look at the presentations delivered by Scott Guthrie, Tim Heuer, Brad Abrams and many more

K