Monthly Archives: June 2014

MVVM Cross Basics – Navigating Using Commands

I’m quite new to MVVM Cross. I thought I’d start another series of posts on my progress (I haven’t forgotten about the others). Especially where I haven’t found as much documentation as I’d like. My latest project is a game written using the MVVM Cross framework; it’s not a shoot-em-up or an action game, but it will be a game. When it’s finished, I’ll post a link if I get it in any of the stores.

Quick Tips

So far, the best place to go if you’re new to MVVM Cross is Stuart Lodges videos:

https://www.youtube.com/watch?v=_DHDMNB_IeY

Stuart is also a regular of Stack Overflow.

Navigation

The way that MVVM Cross works is slightly different to what I would have expected, in that the ViewModel is the key to the navigation. The view is then determined using a naming convention. In this example, I’m starting the application in a ViewModel called Home, and navigating to Main. Home will display the “New Game / Continue Game” dialog, and Main will be the main game screen.

This blog post is not intended to show how to set-up a new MVVM Cross project; however, essentially my game architecture is as follows:

Game Solution
– Game.PCL
– Game.Windows
– Game.WindowsPhone (currently disabled as this doesn’t work)
– Game.Shared

I have no idea whether this will work, but I think it should. If it doesn’t then I’m sure there’ll be some useful lessons on the way.

MvxCommand – the ViewModel

There is a in-built command type called MvxCommand, and that is what I’m going to use. Here’s how I set-up my VM:

    public class HomeViewModel : BaseViewModel
    {
        private MvxCommand _startNewGameCommand;
        private MvxCommand _continueExistingGameCommand;

        public IMvxCommand StartNewGameCommand
        {
            get
            {
                return _startNewGameCommand;
            }
        }

        public IMvxCommand ContinueExistingGameCommand
        {
            get
            {
                return _continueExistingGameCommand;
            }
        }

        public override void Start()
        {
            _startNewGameCommand = new MvxCommand(() => StartNewGame());
            _continueExistingGameCommand = new MvxCommand(() => ContinueExistingGame());

            base.Start();
        }

        private void ContinueExistingGame()
        {
            throw new NotImplementedException();
        }

        private void StartNewGame()
        {
            ShowViewModel<MainViewModel>();
        }
    }

ShowViewModel is the key here. It navigates to the MainViewModel. MVVMCross uses a convention whereby the view that is shown is based on the VM name; so the view here must be called MainView.

The View

The source view (In this case HomeView) looks like this:

<views:MvxStorePage
    x:Class="MyGame.Views.HomeView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:views="using:Cirrious.MvvmCross.WindowsStore.Views"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button Command="{Binding StartNewGameCommand}" HorizontalAlignment="Center">Start New Game</Button>
            <Button Command="{Binding ContinueExistingGameCommand}" HorizontalAlignment="Center">Continue Existing Game</Button>
        </StackPanel>
    </Grid>
</views:MvxStorePage>

Pretty simple command binding. Now, providing that the destination View and ViewModel exist, and inherit from MvxStorePage, your navigation should now work.

Conclusion

Just the rest of the game to write now…

Mock Current Date and Time in SQL Server

Occasionally, if you’re especially lucky, you’ll get into a situation where you have SQL procedures and functions that are so complicated that they require unit tests all of their own. They’ll have business logic embedded in them, and not testing them will leave a massive hole in your test coverage.

In this blog post I’m not going to describe how to do that – SSDT are quite well documented anyway. This is about how to deal with dates and times in SQL Server.

A new function

You’ll probably have a few places in your SQL script that call the following:

SELECT GETUTCDATE()

Or, you may even have the following:

SELECT GETDATE()

Which will presumably work well for what you want. Of course, the problem that you have here is, that for unit tests, this presents a variable factor in your test; that is, you’re not always testing the same procedure. Take the following segments of SQL for example:


PROCEDURE MYPROC
AS
BEGIN
	DECLARE @today DATETIME
	DECLARE @hasEntriesAfterToday INT
	
	SET @today = GETUTCDATE()

	SELECT @hasEntriesAfterToday = COUNT(*)
	FROM dbo.MyTable t
	WHERE t.Col1 > @today

	IF (@hasEntriesAfterToday > 0) 	
		select 'test'
END
GO

MyTable contains many entries after today, and my test checks that it returns ‘test’, so the test works, the code works and I’m going to bed.

But what happens in a year’s time?

Let’s say that the last entity in that table is 01/01/2015 (that way the post works in the US, too). As I write this, it is mid-way through June. So, I need to know what will happen on 2nd January 2015. If I do nothing then when it is 2nd January 2015 the test will start to fail, and I won’t know why.

Abstract the date

When faced with this problem, my initial fix was as follows:

CREATE FUNCTION dbo.MyGetDate()
RETURNS DATETIME
AS
BEGIN
	DECLARE @today DATETIME
	SET @today = GETUTCDATE()

	RETURN @today
END

And then simply change the above procedure to call this. That certainly works; however, as soon as you start to reference this function (for example, you set a default value for a date in a table), you’ll find that you’ll get stuck when you try to mock it out; consequently, you need a double layer:

CREATE FUNCTION dbo.MyGetDate2()
RETURNS DATETIME
AS
BEGIN
	DECLARE @today DATETIME	
	SET @today = GETUTCDATE()

	RETURN @today
END
GO

CREATE FUNCTION dbo.MyGetDate()
RETURNS DATETIME
AS
BEGIN
	DECLARE @today DATE	
	SET @today = dbo.MyGetDate2()

	RETURN @today
END
GO

What this then allows you to do is to replace the function of MyGetDate2 without affecting MyGetDate. This is a wrapper function to replace the DateTime:

internal static void OverrideDateTimeTest(SqlConnection cn, SqlTransaction tr, string newDateTime)
{
    string sql =
        "ALTER FUNCTION dbo.MyGetDate2(	" +
        ") RETURNS datetime " +
        "AS " +
        "BEGIN " +
        "DECLARE @value datetime " +
        "SET @value = convert(datetime, '" + newDateTime + "') "  +
        "RETURN @value " +
        "END";
 
    using (SqlCommand cmd = new SqlCommand(sql, cn, tr))
    {
        cmd.Connection = cn;
        cmd.CommandType = CommandType.Text;
        cmd.ExecuteNonQuery();
    }
}

And here’s the test:

[TestMethod]
public void MyTest()
{
    DBWrapper.OverrideDateTimeTest(cn, tr, "2014-06-10 22:30:00.000");
    Assert.AreEqual( …

The best part about this is that IN SQL SERVER DDL STATEMENTS CAN BE ROLLED BACK! Look at the following test:


-- 1
BEGIN TRAN
GO

-- 2
SELECT dbo.MyGetDate()
GO

-- 3
ALTER FUNCTION [dbo].[MyGetDate2]()
RETURNS DATETIME
AS
BEGIN
	DECLARE @today DATETIME
	SET @today = GETUTCDATE()

	RETURN @today
END
GO

-- 4
SELECT dbo.MyGetDate()
GO

-- 5
ALTER FUNCTION [dbo].[MyGetDate2]()
RETURNS DATETIME
AS
BEGIN
	DECLARE @today DATETIME
	SET @today = CONVERT(DATETIME, '2014-06-10 22:30:00.000')

	RETURN @today
END
GO

-- 6
SELECT dbo.MyGetDate()
GO

-- 7
ROLLBACK TRAN
GO

-- 8
SELECT dbo.MyGetDate()
GO

Okay – there’s a fair amount of code, but the stages are as follows (numbered):

1. Start the transaction.
2. Show the existing implementation of MyGetDate2 (in case it’s not what it should be).
3. Change MyGetDate2 to use GetUTCDate(), so it should be the same as before.
4. Check again – should still return the same as 2.
5. Change MgGetDate2 to return hard coded date.
6. Check that it now returns a hard coded date.
7. Rollback the transaction.
8. The transaction is rolled back, and so the function behaves as in 1.

Conclusion

So, we can include a date mock in our test and, should there be a problem, or when we’re finished, it all gets rolled back. Just because I’m always cautious about such things, I’ve created a test that checks that the default implementation returns the current date, but you shouldn’t need this.

Loading a Twitter Feed in WinRT

Recently, Twitter in their wisdom, discontinued the support for atom feed.  I have a couple of programs that were interrogating this, and they all suddenly (and gracefully I might add) stopped working.

The changeover is not that straightforward, especially if you don’t want to use third party libraries.

Introduction and Caveat

What I’m trying to achieve with this post is to collate all the information that I’ve gathered into a single place, so that switching from the old atom Twitter search:

string atomTweetSearchURL = string.Format("http://search.twitter.com/search.atom?q={0}", searchText);

…to the new OAuth2 can be achieved without looking anywhere else.

This is based on a Windows Store app.  There are some features that will be specific to a Store App, but I have no reason to believe this wouldn’t be generally applicable (and possible in a similar fashion) outside of the RT environment.  Having said that, there are other resources more applicable if you have access to the full .NET framework.

Finally, I have made use of lots of internet help. Where possible, I’ll link the appropriate articles, but if I forget to, just assume that the code you see here was either directly taken, or adapted from something I found online.

A last point, if you use libraries such as Linq to Twitter and JSON.NET, you’ll make your life easier; personally, I wanted to do this without a third party library.

Twitter Configuration

Previously, the URL above would allow you to simply interrogate the Twitter stream and Twitter didn’t need to know about who you were. That is now replaced. You don’t necessarily need to log-in as a user, you can use Application Only Identification. To set this up, visit https://apps.twitter.com/app/new

twitterappdetails

Only the first three boxes are required information. If you are developing a Windows 8 App then the Website can be a deep link to your application; for example, mine was here:

http://apps.microsoft.com/windows/app/geegeeeight/26d0e292-ca89-4ad6-bddc-cde3f2f9e7eb

Once you click on the button to create a new app:

CreateTwitterApp

You will be provided with a Key and a Secret. These are long strings of numbers and letters that will identify your app.

JSON Helpers

We’ll be dealing in JSON. As such, you need to be able to serialise and de-serialise JSON data. The first thing to do is to create a helper class such as follows:

    class JSonSerialiserHelper
    {

        public static T Deserialize<T>(string json)
        {
            var _Bytes = Encoding.Unicode.GetBytes(json);
            using (MemoryStream _Stream = new MemoryStream(_Bytes))
            {
                var _Serializer = new DataContractJsonSerializer(typeof(T));
                return (T)_Serializer.ReadObject(_Stream);
            }
        }

        public static string Serialize(object instance)
        {
            using (MemoryStream _Stream = new MemoryStream())
            {
                var _Serializer = new DataContractJsonSerializer(instance.GetType());
                _Serializer.WriteObject(_Stream, instance);
                _Stream.Position = 0;
                using (StreamReader _Reader = new StreamReader(_Stream)) 
                { return _Reader.ReadToEnd(); }
            }
        }
    }

You’ll also need to deal with dates, so add this, too:

        internal static DateTime ConvertDate(string dateIn)
        {
            // http://blog.kevinyu.org/2012/07/handling-json-in-net.html
            const string Const_TwitterDateTemplate = "ddd MMM dd HH:mm:ss +ffff yyyy";
            DateTime createdAt = DateTime.ParseExact(dateIn, Const_TwitterDateTemplate, new System.Globalization.CultureInfo("en-GB"));

            return createdAt;
        }

Obviously if you’re not in Britain you may wish to change the culture.

Get a Token

There is now a two step authentication; it works like this:
1. Send your application details (key and secret) to Twitter and get an Authorisation Token
2. Use the token to search Twitter with your criteria

The Key and Secret are what you obtained above when you registered your app; the code below should get you a token with that information:

        // http://stackoverflow.com/questions/22733283/twitter-oauth2-using-winrt
        private async Task<TwitAuthenticateResponse> TwitterOAuth(string key, string secret)
        {
            var client = new HttpClient();
            var uri = new Uri("https://api.twitter.com/oauth2/token");

            var encodedConsumerKey = WebUtility.UrlEncode(key);
            var encodedConsumerSecret = WebUtility.UrlEncode(secret);
            var combinedKeys = String.Format("{0}:{1}", encodedConsumerKey, encodedConsumerSecret);
            
            var utfBytes = System.Text.Encoding.UTF8.GetBytes(combinedKeys);
            var encodedString = Convert.ToBase64String(utfBytes);

            client.DefaultRequestHeaders.Add("Authorization", string.Format("Basic {0}", encodedString));

            var data = new List<KeyValuePair<string, string>> 
            { 
                new KeyValuePair<string, string>("grant_type", "client_credentials") 
            };

            var postData = new FormUrlEncodedContent(data);

            var response = await client.PostAsync(uri, postData);
            TwitAuthenticateResponse authenticationResponse;
            using (response)
            {
                if (response.StatusCode != System.Net.HttpStatusCode.OK)
                    throw new Exception("Error.  Authentication Failed.");

                var content = await response.Content.ReadAsStringAsync();
                authenticationResponse = JSonSerialiserHelper.Deserialize<TwitAuthenticateResponse>(content);
                if (authenticationResponse.token_type != "bearer")
                    throw new Exception("Wrong result type.  Authentication failed.");

                return authenticationResponse;
            }            
        }

TwitAuthenticateResponse looks like this:

    public class TwitAuthenticateResponse
    {
        public string token_type { get; set; }
        public string access_token { get; set; }        
    }

If you call that, you should have a valid token:

var auth = await TwitterOAuth("key", "secret");

Now the search

Now you have the authentication, you can use that to call the search; here’s the code:

        // http://stackoverflow.com/questions/23671600/using-a-token-to-search-on-twitter-with-oauth2
        private async Task<string> SearchTwitter(string accessToken, string srchStr)
        {
            var client = new HttpClient();
            var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);
            var uri = new Uri(searchUrl);

            client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", accessToken));

            HttpResponseMessage response = await client.GetAsync(uri);
            string content = await response.Content.ReadAsStringAsync();

            return content;
        }

And here’s the call:

string srch = await SearchTwitter(auth.access_token, searchText);

What to do with the results?

Okay – you can use JSON.NET as mentioned before; however, here’s a way to do it without.

First, you need to declare some classes to hold the data:

    public class TwitSearchResult
    {
        public StatusClass[] statuses { get; set; }

    }

    public class TwitUser
    {
        public string ScreenName { get; set; }
    }

    public class StatusClass
    {
        public string text { get; set; }
        public string source { get; set; }
        public TwitUser user { get; set; }
        public string created_at { get; set; }
    }

Finally, use the helper classes above to deserialise what you get back:

            TwitSearchResult srchResult = JSonSerialiserHelper.Deserialize<TwitSearchResult>(srch);

Summary

The final top level call now looks like this:

            var auth = await TwitterOAuth("key", "secret");
            string srch = await SearchTwitter(auth.access_token, searchText);

            TwitSearchResult srchResult = JSonSerialiserHelper.Deserialize<TwitSearchResult>(srch);

Conclusion

Like I said before, if I’ve used your code and not credited you then it’s not intentional. My aim was just to get all this into a single place for future reference. If you’d like me to reference anything that isn’t referenced then contact me or leave a message.

Windows Tile Updater (Part 7 – Multibinding command parameters)

We left the last post where the Tile Updater could update text, or images, but we basically had to choose which at design time. In this post, I’m going to pass through the image and text, and have the command work out which to update.

Note: you can have both image and text in live tiles. Look out for that in a future post.

Multibinding

The first thing to know about multibinding for WinRT is that it doesn’t exist. However, to get around this, we can simply take the same approach that we do with a function – a function can only return one value, but that value can be a class; so we’ll bind to the VM (one of the advantages of exposing a static singleton instance of the VM):

<Button Grid.Row="2" Command="{Binding UpdateCommand}" CommandParameter="{Binding MVM}">Update</Button>        

The command itself needs to look something like this for now:

        public bool CanExecute(object parameter)
        {
            MainViewModel mvmInst = (MainViewModel)parameter;
            if (mvmInst == null) return false;

            if (string.IsNullOrWhiteSpace(mvmInst.ImagePath) &amp;&amp; string.IsNullOrWhiteSpace(mvmInst.DisplayText))
                return false;
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            MainViewModel mvmInst = (MainViewModel)parameter;

            if (string.IsNullOrWhiteSpace(mvmInst.ImagePath))
                TileUpdater.Model.UpdateTile.UpdateTileText(mvmInst.DisplayText);
            else
                TileUpdater.Model.UpdateTile.UpdateTileImage(mvmInst.ImagePath);
        }

There’s a couple of points here:
1. The CanExecute will not prevent the command from firing where neither parameter has a value.
2. It doesn’t disable the button when this occurs.

And that’s it – we now have a command that can accept multiple parameters and update either image or text depending on what is displayed.

Conclusion

Okay, strictly speaking, this is not multi-binding. It does however, solve the problem. I suppose the design question would be: does it introduce a tighter coupling than multi-binding?

It definitely does; however, with a bit of manipulation, you could introduce a mini-VM that just had the parameters that you need. However, for most cases, I would think that it was fine to just pass the VM to the command. We’ll see if this comes back to bite me when we start putting some unit tests in place.

Windows Tile Updater (Part 6 – Binding a command parameter)

We’re still missing functionality to show the text, or show the text and an image where both are specified.

Add text

Let’s start with the text field. It’s currently just hard coded – that’s pretty straightforward:

        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="{Binding DisplayText, Mode=TwoWay}" Margin="10"/>
        </StackPanel>

Next, let’s hook this up to the command.

<Button Grid.Row="2" Command="{Binding UpdateCommand}" CommandParameter="{Binding DisplayText}">Update</Button>

So that works, and the logic to show the text tile is quite straightforward:

        public static void UpdateTileText(string text)
        {
            XmlDocument xmlDoc = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Text01);

            XmlElement textNode = (XmlElement)xmlDoc.GetElementsByTagName("text")[0];
            textNode.InnerText = text;

            Windows.UI.Notifications.TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
            TileNotification tileNotification = new TileNotification(xmlDoc);
            tileUpdater.Update(tileNotification);
        }

So, we can call this, or we can call the UpdateImage. At the moment, we can’t call both. In the next post I’ll look at how we can do this using Multibinding.