Jul 27, 2007

Simple animated WPF application - with no line of code

Playing around with Microsoft Expression Blend 2 May CTP I noticed that this tool got much better since my last trial in September 2006. There is even already an August CTP ready for download.

So let's create a simple WPF application without writing one line of code. After starting or when the "Hello World" text is clicked, it should turn around it's upper x axis.


- color the window Background with a red-to-black gradient brush
- add a StackPanel to the default Grid type LayoutRoot under window
- add a Rectange below the Stackpanel that is filled with a black-to-white gradient brush (with a 35% opacity)
- also add a label to the LayoutRoot with the "Hello World" Content
- in the "Objects and Timeline" window add a new timeline "TurnLable"
- select the label and move the timeline to 1 second where you modify the RenderTransform property to translate in the Y direction (-48) and scale Y (-1)
- select the lable and move the timeline to 2 seconds where you set the RenderTransform translation Y back to 0 and the scale Y to 1
- in the Triggers window add a Window.Loaded trigger that Begins a TurnLable
- in the Triggers window add a Window.MouseDown trigger that does the same



Et voilà!

Here's the XAML for reference:

<Window

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    x:Class="BookCover.Window1"

    x:Name="Window"

    Title="Window1"

    Width="640" Height="480" Background="{DynamicResource BlackRedGradient}">

 

    <Window.Resources>

        <LinearGradientBrush x:Key="BlackRedGradient" EndPoint="1,0.5" StartPoint="0,0.5">

            <GradientStop Color="#FF000000" Offset="0"/>

            <GradientStop Color="#FF790606" Offset="1"/>

        </LinearGradientBrush>

        <Storyboard x:Key="TurnLable">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="-48"/>

                <SplineDoubleKeyFrame KeyTime="00:00:02" Value="0"/>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="0"/>

                <SplineDoubleKeyFrame KeyTime="00:00:02" Value="0"/>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="-1"/>

                <SplineDoubleKeyFrame KeyTime="00:00:02" Value="1"/>

            </DoubleAnimationUsingKeyFrames>

        </Storyboard>

    </Window.Resources>

 

    <Window.Triggers>

        <EventTrigger RoutedEvent="FrameworkElement.Loaded">

            <BeginStoryboard x:Name="TurnLable_BeginStoryboard" Storyboard="{StaticResource TurnLable}"/>

        </EventTrigger>

        <EventTrigger RoutedEvent="Mouse.MouseDown">

            <BeginStoryboard Storyboard="{StaticResource TurnLable}"/>

        </EventTrigger>

    </Window.Triggers>

 

    <Grid x:Name="LayoutRoot">

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="*"/>

        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>

            <RowDefinition Height="0.29*"/>

            <RowDefinition Height="0.389*"/>

            <RowDefinition Height="0.321*"/>

        </Grid.RowDefinitions>

        <Label RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" Margin="161,52.08,0,0" x:Name="label" VerticalAlignment="Top" Content="Hello WPF" FontFamily="Verdana" FontSize="48" Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" Grid.Row="1">

            <Label.RenderTransform>

                <TransformGroup>

                    <ScaleTransform ScaleX="1" ScaleY="1"/>

                    <SkewTransform AngleX="0" AngleY="0"/>

                    <RotateTransform Angle="0"/>

                    <TranslateTransform X="0"/>

                </TransformGroup>

            </Label.RenderTransform>

        </Label>

        <StackPanel Margin="0,129.92,0,0" Grid.RowSpan="2">

            <Rectangle Opacity="0.35" Stroke="#FF000000" Width="633.6" Height="174.272">

                <Rectangle.Fill>

                    <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">

                        <GradientStop Color="#FF000000" Offset="0"/>

                        <GradientStop Color="#FFFFFFFF" Offset="1"/>

                    </LinearGradientBrush>

                </Rectangle.Fill>

            </Rectangle>

        </StackPanel>

        <ToolBarPanel Opacity="1" Margin="0,0,0,61.92">

            <StackPanel Height="100">

                <ToolBar Width="100" Height="100">

                    <Button Width="100" Height="100" Content="Button" Foreground="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>

                </ToolBar>

                <Label ToolTip="This is my toolbars tool tip!" Width="100" Height="100" Content="Hello Markus" Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" Panel.ZIndex="0"/>

            </StackPanel>

        </ToolBarPanel>

    </Grid>

</Window>

Namespace Naming

Just came across an MSDN article talking about namespace naming guidelines under http://msdn2.microsoft.com/en-us/library/893ke618(VS.71).aspx

In summary:

namespace <companyname>.<product>.<feature>.<sub-feature>


So think twice when your namespaces should fit for the next ten years.

Where custom Exceptions should derive from?

A common question is whether your application specific exceptions should base on System.ApplicationException or from System.Exception?

I stick to Cwalina/Abrams (Framework Design Guidelines/Addison Wesley) position to use System.Exception as a base class.

The reason for this is that ApplicationException was indeed once thought as a base for all custom application exceptions, but was misused in some .NET framework exceptions as well.

Jul 18, 2007

1 host, 2 services, 1 endpoint each, but only 1 port ?

The question came up, if it would be possible to host two or more WCF services (in the same executable to be precise) on the same port using the WSHttpBinding binding?

I wrote a little test and the question is: Yes. I'm guessing this is due to the fact that WCF only uses one listener here and there is no port conflict. Using WSDualHttpBinding would probably cause conflicts on the callback ports (if there is more than one client executable (WCF listener) implementing the callback service).

Port sharing also works for the TCP binding. However, throws an exception when bindings are mixed (one service to use HTTP and the other TCP)

Jul 17, 2007

Manage the instance object for a WCF service

On certain occassions it may be necessary to control the creation and destruction of your WCF service instances (that may be create per call, per session or single).

Therefore you need to implement IInstanceProvider:

public class MyServiceInstanceProvider : IInstanceProvider

{

    public object GetInstance(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.Channels.Message message)

    {

        object instance = null;

 

        instance = new MyService();

 

        return instance;

    }

 

    public object GetInstance(System.ServiceModel.InstanceContext instanceContext)

    {

        return GetInstance(instanceContext, null);

    }

 

    public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)

    {

        IDisposable disposableInstance = instance as IDisposable;

        if (disposableInstance != null) disposableInstance.Dispose();

    }

}


and IServiceBehavior (where the custom provider is attached to the endpoints)

public class MyServiceServiceBehavior : IServiceBehavior

{

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)

    {

        foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)

        {

            ChannelDispatcher cd = cdb as ChannelDispatcher;

            if (cd != null)

            {

                foreach (EndpointDispatcher ed in cd.Endpoints)

                {

                    ed.DispatchRuntime.InstanceProvider = new MyServiceInstanceProvider();

                }

            }

        }

    }

 

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

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

}


The service behavior is added in code here

ServiceHost serviceHost = new ServiceHost(typeof(MyService));

serviceHost.Description.Behaviors.Add(new MyServiceServiceBehavior());

serviceHost.Open();

Jul 16, 2007

WCF throttling and DoS prevention

To enable restrictions on the number of clients and the load they place on a WCF service the following options are available:
- limit the maximum number of concurrent sessions
- limit the number of concurrent calls
- limit the maximum number of concurrent instances
This is available in service haviour settings.

Furthermore there is TransportBindingElement.MaxReceivedMessageSize that
- limit the maximum received payload. This defaults to 64kB.

As Nicholas Allen points out there are even more settings possible, e.g. with Transport Quotas.

Jul 9, 2007

WCF error practices / Faults

I recently gave a half-day training for a group of Windows embedded developers and decided to talk about error handling practices in WCF services (beside the mandatory topics of Architecture, Contracts, Bindings, Hosting, Security and Versioning).

First of all, the contract needs to be decorated with a FaultContract definition to prepare clients about what to expect concerning SOAP exceptions (faults):

[ServiceContract(Namespace="http://www.mleder.blogspot.com/EES/WME/Camp2007/06/20")]

public interface IWmeService

{

    [OperationContract]

    [FaultContract(typeof(WmeFault))]

    WmeRes SayHello(WmeRequest req);

}


WmeFault is a simple custom DataContract class of ours

[DataContract]

public class WmeFault

{

    private string why;

    [DataMember]

    public string Why

    {

        get { return why; }

        set { why = value; }

    }

 

    public WmeFault(string why)

    {

        this.Why = why;

    }

}


In the service implementation you just throw an exception with this type

public class WmeService : IWmeService

{

    public WmeRes SayHello(WmeRequest req)

    {

        if (req.Text.Contains("Markus"))

        {

            throw new FaultException<WmeFault>(new WmeFault("no, Markus"));

            // throw new FaultException("no, Markus");

        }

 

        WmeRes wmeRes = new WmeRes();

        return wmeRes;

    }

}


And on the client side we catch our nicely-modeled SOAP fault message as we always do with regular System.Exception.

try

{

    WmeRequest req = new WmeRequest();

    req.Text = text;

    wmeService.SayHello(req);

}

catch (FaultException<WmeFault> fex)

{

    Console.WriteLine("Client fault FaultException<WmeFault> : " + fex.Detail.Why);

}