Working with JSON web services in Silverlight and Windows Phone 7

In this post I’ll explain how to retrieve and display data from JSON web services.

As an example I’ll use the REST service from geonames.org.

JSON response of the example looks so:

At first, you should create C# classes (models) which can be mapped to JSON entities.
The first curly braсe indicates that it is an object, and it has 1 property `geonames`. After this property you can see the square bracket indicating an array. This array consists of many objects, and each object has 12 properties.
So we should create a model for the root object, which looks so:

// { geonames: [{}, {}, {}] }
[DataContract]
public class CitiesList
{
	[DataMember(Name = "geonames")]
	public List<City> Cities { get; set; }
}

It is important to add DataContract and DataMember attributes to the class and all its properties. Also you should specify the name of the corresponding JSON property (geonames) inside the DataMember attribute.

Then we should create the model for inner objects (cities). As you already saw, each JSON object has 12 properties, but we don’t need all of them. So we can specify only those proeprties which we need, and .Net deserializer will ignore all other properties.

// { name: "", countrycode: "", population: -1 }
[DataContract]
public class City
{
	[DataMember(Name = "name")]
	public string Name { get; set; }

	[DataMember(Name = "countrycode")]
	public string CountryCode { get; set; }

	[DataMember(Name = "population")]
	public int Population { get; set; }
}

So now all that you need is to create an instance of the HttpWebRequest class, get the response and deserialize it by using the DataContractJsonSerializer class. The deserializer requires the System.Servicemodel.Web and System.Runtime.Serialization references.

You must use the two following methods to perform loading and parsing of JSON.

private void BeginDownloadCitiesRequest()
{
	// create the http request
	HttpWebRequest httpWebRequest = WebRequest.CreateHttp("http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=en&username=vortexwolf");
	httpWebRequest.Method = "GET";
	httpWebRequest.Accept = "application/json";

	// get the response asynchronously
	httpWebRequest.BeginGetResponse(OnGetResponseCompleted, httpWebRequest);
}

private void OnGetResponseCompleted(IAsyncResult ar)
{
	var httpWebRequest = (HttpWebRequest)ar.AsyncState;

	// get the response
	var response = httpWebRequest.EndGetResponse(ar);

	// deserialize json
	var jsonSerializer = new DataContractJsonSerializer(typeof(CitiesList));
	var responseObject = (CitiesList)jsonSerializer.ReadObject(response.GetResponseStream());

	// display on the view
	Deployment.Current.Dispatcher.BeginInvoke(() => OnCitiesDownloaded(responseObject));
}

The code of creating a http request and getting a response will often repeat in different places of the application, so it is preferrable to move this code to a separate class.
I did it so:

public class HttpGetTask<T>
{
    public HttpGetTask(string url, Action<T> onPostExecute)
    {
        this.Url = url;
        this.OnPostExecute = onPostExecute;
    }

    public void Execute()
    {
        if (this.OnPreExecute != null)
        {
            this.OnPreExecute();
        }

        // create the http request
        HttpWebRequest httpWebRequest = WebRequest.CreateHttp(this.Url);
        httpWebRequest.Method = "GET";
        httpWebRequest.Accept = "application/json";

        // get the response asynchronously
        httpWebRequest.BeginGetResponse(OnGetResponseCompleted, httpWebRequest);
    }

    private void OnGetResponseCompleted(IAsyncResult ar)
    {
        var httpWebRequest = (HttpWebRequest)ar.AsyncState;

        // get the response
        HttpWebResponse response;
        try
        {
            response = (HttpWebResponse)httpWebRequest.EndGetResponse(ar);
        }
        catch (WebException)
        {
            this.InvokeOnErrorHandler("Unable to connect to the web page.");
            return;
        }
        catch (Exception e)
        {
            this.InvokeOnErrorHandler(e.Message);
            return;
        }

        if (response.StatusCode != HttpStatusCode.OK)
        {
            this.InvokeOnErrorHandler((int)response.StatusCode + " " + response.StatusDescription);
            return;
        }

        // response stream
        var stream = response.GetResponseStream();

        // deserialize json
        var jsonSerializer = new DataContractJsonSerializer(typeof(T));
        var responseObject = (T)jsonSerializer.ReadObject(stream);

        // call the virtual method
        this.InvokeInUiThread(() => this.OnPostExecute(responseObject));
    }

    private void InvokeOnErrorHandler(string message)
    {
        if (this.OnError != null)
        {
            this.InvokeInUiThread(() => this.OnError(message));
        }
    }

    private void InvokeInUiThread(Action action)
    {
        Deployment.Current.Dispatcher.BeginInvoke(action);
    }

    public string Url { get; private set; }

    public Action<T> OnPostExecute { get; private set; }

    public Action OnPreExecute { get; set; }

    public Action<string> OnError { get; set; }
}

You can execute this task by specifying Url and the OnPostExecute callback. Also you can set other properties. Example:

public class MainViewModel : INotifyPropertyChanged
{
    public MainViewModel()
    {
        Cities = new ObservableCollection<CityViewModel>();

        string url = "http://api.geonames.orgzz/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=en&username=vortexwolf";
        
        var task = new HttpGetTask<CitiesList>(url, this.OnPostExecute);
        task.OnPreExecute = this.OnPreExecute;
        task.OnError = this.OnError;

        task.Execute();
    }

    private void OnPreExecute()
    {
        this.IsLoading = true;
    }

    private void OnPostExecute(CitiesList responseObject)
    {
        this.OnCitiesDownloaded(responseObject);
        this.IsLoading = false;
    }

    private void OnError(string message)
    {
        MessageBox.Show(message);
        this.IsLoading = false;
    }

    public ObservableCollection<CityViewModel> Cities { get; set; }

    private bool _isLoading;

    public bool IsLoading
    {
        get { return _isLoading; }
        set
        {
            _isLoading = value;
            RaisePropertyChanged("IsLoading");
        }
    }

    private void OnCitiesDownloaded(CitiesList citiesList)
    {
        var cityModels = citiesList.Cities
            .Select(c =>
                    new CityViewModel
                    {
                        Name = c.Name,
                        CountryCode = c.CountryCode,
                        Population = c.Population
                    })
            .ToList();

        cityModels.ForEach(this.Cities.Add);
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

I created the sample application for Windows Phone 7 which retrieves JSON data and displays it on the phone.

The source code of the example you can download here: https://dl.dropbox.com/u/8047386/WordPress/PhoneJsonTest.zip

Silverlight and WPF Timeline Scroll View

Here is another control which I had for a long time but only recently have decided to arrange the source code and post it here.
That’s how it looks:

Although it looks very complex, actually it is quite simple: it is just the styled ScrollBar control on the left and the ScrollViewer on the right.

The grey control with years on the left is the UserControl called TimelineScrollBar, mark-up of which looks so:

<Grid>
	<ItemsControl x:Name="rowItems">
		<ItemsControl.ItemTemplate>
			<DataTemplate>
				<Grid Height="{Binding Height}">
					<TextBlock Text="{Binding Text}"/>
				</Grid>
			</DataTemplate>
		</ItemsControl.ItemTemplate>
	</ItemsControl>

	<!-- ... -->

	<ScrollBar x:Name="VerticalScrollBar" Style="{StaticResource TimeLineScrollBarStyle}" />
</Grid>

The rowItems items control and the VerticalScrollBar scroll bar are related to the dependency properties TimeItemsSource and BoundScrollviewer which should be set outside and are handled in the code-behind:

<Views:TimelineScrollBar x:Name="timelineScroller" 
 TimeItemsSource="{Binding TimelineItems}" 
 BoundScrollViewer="{Binding ElementName=listScroller}" 
 Width="120" />

The TimelineItems is the special collection of items { Text, Height}. These properties must be present and they are quite generic, so you can use any labels instead of years.

The generation of these items is the most difficult part, after that everything is quite easy.

Create the view model:

public class MainViewModel
{
	public List<TestItemViewModel> Items { get; private set; }

	public List<TimelineItemViewModel> TimelineItems { get; private set; }
}

Set is as DataContext to the view:

<Grid>
	<Views:TimelineScrollBar x:Name="timelineScroller" 
 TimeItemsSource="{Binding TimelineItems}" 
 BoundScrollViewer="{Binding ElementName=listScroller}" 
 Width="120" />

	<ScrollViewer x:Name="listScroller">
		<ItemsControl x:Name="list" ItemsSource="{Binding Items}" ItemTemplate="{StaticResource itemTemplate}" ItemsPanel="{StaticResource itemsControlTemplate}" />
	</ScrollViewer>
</Grid>

In this example I used the ItemsControl class for simplicity. If you want to use it with the ListBox class, you should change its ControlTemplate and retrieve the name of the inner ScrollViewer control so it can be bound to the timeline scroll bar.

The source code of my example you can download here: TimeScrollViewerSample.zip

Silverlight show case: TimeScrollViewerSampleTestPage.html

Windows Phone 7 Validation

Today I downloaded Windows Phone 7 SDK to look how much it is different from Silverlight on desktops and from Android OS development. I created a simple form and decided to implement validation, so I went to google and started to search how it is implemented by other people.

Unfortunately, there was very little information about it: the search results page contained lots of irrelevant results like “windows phone activation key” and other strange words. The answers from StackOverflow.com also weren’t ideal: they recommended to use exceptions inside properties or create a custom control inherited from TextBox and create a bunch of properties.

That’s why I’ve decided to spend my time and to write a post how the validation can be implemented with little efforts.
My validation will be based on the INotifyDataErrorInfo interface and I’ll use the validation classes which I developed for WPF and Silverlight here.

Here is the screenshot of the application at the end:

Page layout

At first you need to create the layout with correct bindings:

<StackPanel Grid.Row="1" Margin="12">
	<TextBlock Text="First Name:" />
	<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}" Style="{StaticResource ValidationTextBoxStyle}" />
	<TextBlock Text="Last Name:" />
	<TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}"  Style="{StaticResource ValidationTextBoxStyle}" />
	<Button HorizontalAlignment="Center" Content="Save" Click="SaveButton_Click" />
</StackPanel>
  • The TwoWay binding is important, because you need to send the entered by user data back to the view model.
  • Next necessary property is ValidatesOnNotifyDataErrors, it is used because of the INotifyDataErrorInfo interface. If I used validation through exceptions, I would put the other property (ValidatesOnExceptions) inside the binding. But this interface much better than exceptions.
  • The last binding property is NotifyOnValidationError whose name is very confusing with the previous property. But the previous property is raised first and retrieves errors from the view model. The current property is raised after that and it calls the BindingValidationError event of the view.

TextBox visual feedback

Next issue which I’ve encountered is that WP7 controls don’t have build-in validation feedback. So you should create your own visual states and provide visual feedback. I’ve copied the existing style of the TextBox control by using Expression Blend and slightly changed it.
Earlier it looked so:

<ControlTemplate TargetType="TextBox">
	<Grid Background="Transparent">
		<VisualStateManager.VisualStateGroups>
			<!-- Visual States -->
		</VisualStateManager.VisualStateGroups>
		<!-- Borders -->
	</Grid>
</ControlTemplate>

I added validation states and controls:

<ControlTemplate TargetType="TextBox">
	<StackPanel Background="Transparent">
		<VisualStateManager.VisualStateGroups>
			<!-- Visual States -->
			<VisualStateGroup x:Name="ValidationStates">
				<VisualState x:Name="Valid" />
				<VisualState x:Name="Invalid" >
					<Storyboard>
						<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationBorder">
							<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
						</ObjectAnimationUsingKeyFrames>
						<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationMessage">
							<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
						</ObjectAnimationUsingKeyFrames>
					</Storyboard>
				</VisualState>
			</VisualStateGroup>
		</VisualStateManager.VisualStateGroups>
		<Grid>
			<!-- Borders -->
			<Border x:Name="ValidationBorder" BorderBrush="Red" BorderThickness="2" Visibility="Collapsed" Margin="6,3" />
		</Grid>
		<TextBlock x:Name="ValidationMessage" Foreground="Red" Visibility="Collapsed" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" Margin="6,0" />
	</StackPanel>
</ControlTemplate>

C# code

Than I added to the view the code which changes validation states. You should set the NotifyOnValidationError property to true in bindings so that the BindingValidationError event works.

public MainPage()
{
	InitializeComponent();

	this.DataContext = new MainViewModel();

	this.BindingValidationError += MainPage_BindingValidationError;
}

private void MainPage_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
	var state = e.Action == ValidationErrorEventAction.Added ? "Invalid" : "Valid";

	VisualStateManager.GoToState((Control)e.OriginalSource, state, false);
}

And that’s almost all. The view model class is very simple:

public class MainViewModel : ValidationViewModel
{
	public MainViewModel()
	{
		this.Validator.AddValidationFor(() => this.FirstName).NotEmpty().Show("Enter the first name");
		this.Validator.AddValidationFor(() => this.LastName).NotEmpty().Show("Enter the last name");
	}

	private string firstName;

	public string FirstName
	{
		get { return firstName; }
		set
		{
			firstName = value;
			RaisePropertyChanged("FirstName");
		}
	}

	private string lastName;

	public string LastName
	{
		get { return lastName; }
		set
		{
			lastName = value;
			RaisePropertyChanged("LastName");
		}
	}
}

The ValidationViewModel class you can take from the sample project.
You can download the source code here: WindowsPhoneValidation.zip

WPF Scheduler

Several years ago I found a Silverlight sample application on one of the sites of Microsoft, that application was called something like Patient Journey Demonstrator and didn’t serve any real purpose but to show what can be created by using Silverlight.
I remember that I decompiled the source code and tried to build something similar, but eventually I didn’t used those controls in any of my applications. Anyway, here is one of the interesting controls:

This controls looks good by the way: you can expand and collapse items representing hours, you can drag and drop appointments from one time to another, also there are some unavailable gray cells which it is not allowed to drag items to. The only one inconvenience is that all items should take the same amount of time and can’t cross the border of an hour.

This code is 2 years old and isn’t implemented well, but at least it works. Maybe some day I’ll rewrite it and make it more useful, as soon as I have a time.
Source code: WpfSchedulerSample.zip

WPF Drag and Drop implementation

Some time ago I searched how to implement the drag and drop functionality in my WPF application. But all examples that I found either contained much of unmaintenable code or worked only for a specific task and it was difficult to add that code into my existing application.

But recently in the Microsoft training course book (10262A Developing Windows Applications) I’ve found quite good example how to implement this functionality by using expression blend behaviors. By the way, the actual implementation were taken from this post.

Now it is very easy to use the drag and drop out of the box, just add the following 3 lines to a source element:

<i:Interaction.Behaviors>
    <dd:DragDropBehavior IsDragSource="True"/>
</i:Interaction.Behaviors>

And the following 3 lines to a target element:

<i:Interaction.Behaviors>
    <dd:DragDropBehavior IsDropTarget="True" Dropped="DragDropBehavior_Dropped"/>
</i:Interaction.Behaviors>

The i prefix is defined as xmlns:i=”clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity”, you can use this library after you install Expression Blend SDK or you can find it in the archive attached to this post.

Which element is the source and which one is the target – you should determine it logically. For example, if you want to move items from one ListBox to another one, the drag source will be the item template of the first ListBox (because it is the item which is dragged), the drop target will be the second ListBox itself (although it is still possible to set the drop target to the item template, it doesn’t work well for the empty listbox).
The code will look something like this:

<ListBox ItemsSource="{Binding Items1}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Background="Transparent">
                <i:Interaction.Behaviors>
                    <dd:DragDropBehavior IsDragSource="True"/>
                </i:Interaction.Behaviors>
                        
                <Run Text="{Binding Title}" /><Run Text=": "/><Run Text="{Binding Value}" />
            </TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
        
<ListBox ItemsSource="{Binding Items2}" Grid.Column="1" DisplayMemberPath="Title">
    <i:Interaction.Behaviors>
        <dd:DragDropBehavior IsDropTarget="True" Dropped="DragDropBehavior_Dropped"/>
    </i:Interaction.Behaviors>
</ListBox>

And here is how it looks after you run the application:
wpf drag and drop sample

The source code of the behavior and sample application you can download here: WpfDragDrop.zip
If you want some extra features – you can freely write your suggestions in comments, I’ll think what I can do.

Silverlight Chart with reversed Y axis

Recently on StackOverflow.com I’ve found a question about Silverlight charts:
“Is it possible to display a Y LinearAxis in Silverlight in reversed order? Instead of lower numbers at the bottom increasing to the top of the Y axis, I would like to see lower numbers at the top”.

I can’t imagine where such chart can be used, maybe to display a bad revenue report in the best possible way. The chart on the right looks much better than the left one.

two linear charts comparison

Anyway after lot of efforts I’ve managed to create such axis without changing the source code of the Toolkit library, just by using the inheritance so that you can use it so:

<chart:Chart>
	<cr:ReversedAxisColumnSeries ItemsSource="{Binding Items}" DependentValuePath="Value" IndependentValuePath="Title" />
	<cr:ReversedAxisLineSeries ItemsSource="{Binding Items}" DependentValuePath="Value" IndependentValuePath="Title" />
	<chart:Chart.Axes>
		<cr:ReversedLinearAxis Orientation="Y" />
	</chart:Chart.Axes>
</chart:Chart>

Here is links to the solution and inside the post I’ll describe how I’ve implemented these classes.
Source code: ChartReversedAxisSample.zip
Showcase: TestPage.html
Read more of this post

The necessity of a ViewModel class for each Model class

It is well known that you need a ViewModel if you want to add property change notification or validation to a Model. But what if the Model and ViewModel classes don’t differ at all? Should you create a ViewModel class if it has the same set of properties that the Model class has? The answer is yes, absolutely. The brief reasons are separation of layers and loose coupling. But I know that these abstract terms don’t sound very convincing so I’ll describe my point of view more particularly in this post.

As an example I’ll use this data source class (which can be either a web service, or a database, or a file, whatever) and this model:

public interface IModelSource
{
    SettingsModel GetSettings();
}

public class SettingsModel
{
    public string DefaultPage { get; set; }

    public string DownloadsFolder { get; set; }

    public bool AutoStart { get; set; }
}

So we should choose which approach to use.
Just to bind the model as it is:

SettingsModel model = source.GetSettings();
this.DataContext = model;

Or to use the extra ViewModel layer and convert the model before binding:

SettingsModel model = source.GetSettings();
SettingsViewModel viewModel = ConvertModelToViewModel(model);
this.DataContext = viewModel;

Let’s examine some cases and look at the differences between the approaches above.

 

1. Remove a property from the model class.
It happens quite often during development, this type of changes can be performed on the service side or in the database. So if to remove the AutoStart property, what will happens then?

The model-only approach
You will not be aware of the error and will not notice it until you run your application, navigate to the corresponding view and look at the Output window. There among messy messages you will see the notification about the binding error:
Runtime binding error
Also you should run your application in the Debug mode. If you start it by using the Ctrl+F5 combination, you will never find the error.

The viewmodel approach
You will be notified about the error almost immediately before you run the application. And you know: the earlier the bug is found – the easier to fix it.

 

2. Add a property of a complicated data type to the model class.
For example, this property of the Enum type:

NumberFormatCulture NumberFormat { get; set; }

The model-only approach
It isn’t clear how to bind this enum to the ComboBox control (I think, you will not display such programming language related values as “EnglishUS” to end users, won’t you?), so you’ll search it on Google or StackOverflow and eventually you’ll choose either a hacky solution (which will work only for the particular case) or you’ll agree to use the ViewModel (and admit wasting the time).

The viewmodel approach
Just add a few lines to the mapping configuration which can be easily bound to the ComboBox:

//Mapper.CreateMap ... 
.ForMember(vm => vm.NumberFormats, option => option.UseValue(
    EnumExtensions.GetValues<NumberFormatCulture>().Select(TranslateEnum)))
.ForMember(vm => vm.SelectedNumberFormat, option => option.MapFrom(
    m => TranslateEnum(m.NumberFormat)))

 

3. Change the structure of the model class.
For example, if to change some property of the string type to the property of another model type:

public PageModel DefaultPage { get; set; }

public class PageModel
{
    public string Url { get; set; }
}

The model-only approach
Again, you will not notice the error until you run the application and look at the Ouput Window (see p.1). Then you should run over all the xaml-markup in the view and correct bindings. And of course launch the application once again to assure that everything is fine after the changes.

The viewmodel approach
Just fix one line of the code in the mapping configuration:

//Mapper.CreateMap ... 
.ForMember(vm => vm.DefaultPage, option => option.MapFrom(m => m.DefaultPage.Url))

I must say that in this case the mapper doesn’t perform compile-time checking, but you can configure it so that it throws an exception if you try to map from the object type to the string type. And exceptions are any easier to notice and understand than debug messages in the Output window.

 

4. Project structure and maintenability
It isn’t a big advantage of the viewmodel approach in comparison with the above described points, but anyway, it is much better to have a good project structure when each view has a corresponding view model with the same class name prefix. You will not search which model class is bound to, for example, the SettingsView class (which model class: UserSettingsModel, ServiceSettingsModel? I don’t remember so I’ll take some time to find it out). You’ll just open the folder with view models and immediately see the corresponding SettingsViewModel class.

 

The most popular exuse not to create the extra layer is because it allegedly takes much time. But if to calculate the exact amount, the statement will be far from the truth.
- Add the AutoMapper library by using the NuGet package manager – 20 second (this task is performed only once)
- Create a new ViewModel class and just copypaste all of the properties of the model – 30 seconds
- Configure the mapping by using code-snippets – 5 seconds per property.

So it’ll take something about 1-2 minutes to create a ViewModel and I can’t say that it is a “huge amount of time”. And this amount is nothing in comparison with the time wasted on the above described points if to use the wrong approach. Don’t afraid to spend few minutes now, it will save many hours in the future.

Follow

Get every new post delivered to your Inbox.