Error Code 0x80073CF9

After the latest build of Windows 10 mobile I noticed that my app freeze on the splash page. I tried to re-install it but it failed with the error code 0x80073CF9. I changed setting for touch and then I miraculous manage to install it. The problem with the splash still remained, so I uninstalled the app again so that I could run it in debug mode from Visual Studio. In the development environment the app worked, so I wanted to download it once more from the store. But guess…. same error code and previous workaround didn’t work. Version 2.2.2.0 is based on Silverlight which Microsoft is moving away from. Maybe the problem is related to this technology. I’m currently working on porting it to UWP but isn’t ready to release version 3.0.0.0 yet. When it comes to version 2.2.2.0 it looks like an issue that Microsoft should look into. The app worked on pervious build so to say. Will spend some time to investigate and see if I can find any solution or workarounds, but currently it looks bad for version 2.2.2.0. I hope I can release version 3.0.0.0 in August. Stay tuned!

Culture Aware Validation

It is easy to display a decimal number for any culture in .Net. The formatting support is very comprehensive and you can fine tune it in a number of different ways to suite your particular needs. But how is it to validate a string representing a decimal number from potential any culture with a wide variety of formatting rules? For example, the following strings are the same decimal value displayed according to different cultures: 1,234.56, 1.234,65, 1 234.56 and 1’234.56

In C# I can use the Parse or TryParse method of the numeric type. I tried these for decimal numbers and noticed some unexpected behavior. For the “en-US” culture the decimal separator is a dot. When parsing the string “1.2”, I received the decimal value 1.2, but when parsing “1,2” the function returned 12! I was expecting an error for this string and wonder why I received a value 10 times time greater than the one I intended to write?

After some investigation I learned that comma is the group separator and can be used in an arbitrary way, for example the string “,,,1,,,2,,,” will also be evaluated to 12. I was not so comfortable with this and from my perspective a valid decimal string should look like the formatted string you receive from, for example, the ToString method.

When the framework doesn’t give you the support you want, you have to implement it yourself. I wanted to use a regular expression to validate decimal numbers from any culture in a stricter way. The difference between different representations is the sign for decimal and group separator. .Net framework includes functions that returns current cultures signs. My solution was to create the regular expression dynamically so I could build it during runtime for the culture in use.

string groupSeparator = Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberGroupSeparator;
string decimalSepartor = Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator;
string regularExpression = @"^\d{1,3}([" + groupSeparator + @"]\d{3})*([" + decimalSepartor + @"]\d+)?$";

Actually, I’m a bit reluctant to create my own regular expression, since I’m not sure I know all different formats. It is also easy to make a mistake and preferable I would like to use what is include in the framework. If I find a better way, I will use it instead!

Numeric Keypad in WP 8.1

Received my first support case on my app last week. A user from Russia couldn’t create an expense. To me a bit surprising, since it has been used for a couple of years and no one else have had this issue (to my knowledge). I asked him to write down step by step what he did. When I tried the same procedure, I couldn’t re-produce the problem. It worked very well on my mobile. He mailed me a video showing exactly what he did to make the app crash. This was video was extremely helpful and I immediately suspected what the problem could be. The format of number wasn’t consistent; it was displayed with a comma as decimal separator but he entered it with a dot as decimal separator.

In the page where the problem occurs, I use TextBoxes for numeric fields. A nice feature of TextBox is that you can set the type of input with a parameter called InputScope. This property determines which keyboard layout will be used when the user enters a value. I use Number which let the user to enter values with a numeric keypad.

When have tested my app I have always had a keypad with the right sign of the decimal separator. I have tested the app in a couple of different languages but never had a keypad with wrong decimal separator (unfortunately).

My first question was how do I select which decimal separator sign should be on the keypad? I couldn’t find any API so currently I don’t know how to do it from the code (if anyone knows, please leave a comment). I found out two other ways:

  1. Change keyboard in phone settings.
    By selecting a keyboard for a language that uses another decimal separator I managed to change it.
  2. Long tap on the decimal separator.
    If you long tap the decimal sign, you get a box where you can select which sign to use. You can also select the minus sign if you want to enter a negative number.

NumericKeyLongTapBlogg

The work around for my user was to long tap and select the right decimal separator. While testing this, I realized that many of my users might very well have a keypad with the wrong decimal separator as default. I also found it a bit awkward to enter a decimal separator with long tapping, so in my next version I will simply this.

DeviceFamily

During runtime I can check which device family the application is running on with a call to:


string deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;

The function seems to return a so called “magic” string and I haven’t found any list of valid values published by Microsoft. What values does it return? Is there perhaps a better alternative to figure out what device my app is running on? It’s quite important to know since I will make decisions based on the family type. I also would like some type checking during compile time to ensure that I have used a correct value.

I found a page on Microsoft site called “Guide to Universal Windows Platform (UWP) apps” that is referred to whenever I search on TargetDeviceFamily/DeviceFamily or similar. From this page I conclude that there are six families, but still not fully sure how they are identified by above function. While debugging my desktop and mobile and found out two values, “Windows.Desktop” and “Windows.Mobile”. From various sources (contradictory) on Internet, I think the following additional values are used “Windows.Team“, “Windows.IoT“, “Windows.Xbox” and “Windows.Holographic“. Haven’t found a good way to test this. Anyway, I created a utility class that returns an enumeration instead of a magic string (not sure it is 100% correct though).

public static class DeviceFamilies
{
   public static DeviceFamilyType GetCurrentDeviceFamily()
   {
      string deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;

      switch (deviceFamily)
      {
         case "Windows.Desktop":
            return DeviceFamilyType.Desktop;
         case "Windows.Mobile":
            return DeviceFamilyType.Mobile;
         case "Windows.Team":
            return DeviceFamilyType.Team;
         case "Windows.IoT":
            return DeviceFamilyType.IoT;
         case "Windows.Xbox":
            return DeviceFamilyType.Xbox;
         case "Windows.Holographic":
            return DeviceFamilyType.HoloLens;
         default:
            return DeviceFamilyType.Unknown;
      }
   }
}

public enum DeviceFamilyType
{
   Desktop,
   Mobile,
   Team,
   IoT,
   Xbox,
   HoloLens,
   Unknown
}

MainPage

Much of my inspiration to the application shell comes from Microsoft’s news and financial apps. I have used them on both my mobile and desktop and like the way I interact with them. It is also very easy to create a main page with similar user experience in UWP.

The devices have different screen sizes and I want to adopt the main page depending on size available. Not sure I will support all functionality on all devices and there might be some native behavior I need to consider (for example the back button).

For the desktop client I have both space and resource available. For these devices I can offer almost all features and also make them more apparent in the UI.

MainPageDesktop

The mobile devices have smaller screens and restrictions. I need to be more selective with what features to offer and also to present the information in a way more suitable for the smaller screen size.

MainPageMobile

The SplitView control is perfect for this type of layout. There are different ways to adjust the XAML views for different screen sizes and devices.

I can use Visual State Triggers in XAML. It’s a technique to adapt the UI based on the size of the window. Another way is to use the DeviceFamily-{type} feature. In this approach I can create a particular XAML view per device family. All device specific views will share the same presentation logic (code behind).

I’m still in the beginning of this journey, but I suspect that there will be many differences between in how the views will look on each device. I also think it will be clutter to write one XAML view with a lot of state triggers adjusting it for each device family. Therefore, I decided to create a XAML view per device family (with shared presentation logic) and to separate them by a DeviceFamily folder. Source code is available here.

PrototypeSolutionExplorer

The XAML for the desktop’s MainPage is

<Page
    x:Class="UWP.Prototype.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWP.Prototype.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <RelativePanel Grid.Row="0" Background="LightGray">
            <Button Name="btnNavigator" 
                    Background="LightGray"
                    FontFamily="Segoe MDL2 Assets" 
                    Content="&#xE700;" 
                    FontSize="24"
                    Margin="2,6,6,0"
                    Click="btnNavigator_Click"
                    RelativePanel.AlignLeftWithPanel="True"></Button>
            <CommandBar Name="cmdbarToolbar" RelativePanel.RightOf="btnNavigator">
                <AppBarButton Name="cmdbtnBack"  Icon="Back" Label="Back" />
                <AppBarButton Name="cmdbtnForward" Icon="Forward" Label="Forward"/>
                <AppBarSeparator Name="cmdsepNavigationCrud"></AppBarSeparator>
                <AppBarButton Name="cmdbtnRefresh" Icon="Refresh" Label="Refresh"/>
                <AppBarButton Name="cmdbtnClear" Icon="ClearSelection" Label="Clear"/>
                <AppBarButton Name="cmdbtnSave" Icon="Save"  Label="Save" />
                <AppBarButton Name="cmdbtnAdd" Icon="Add"  Label="Add" />
                <AppBarButton Name="cmdbtnEdit" Icon="Edit"  Label="Edit" />
                <AppBarButton Name="cmdbtnDelete" Icon="Delete" Label="Delete"/>
                <AppBarSeparator Name="cmdsepCrudCancel" ></AppBarSeparator>
                <AppBarButton Name="cmdbtnCancel" Icon="Cancel"  Label="Cancel"/>
            </CommandBar>
        </RelativePanel>
        <SplitView Name="spvwNavigator"
                    Grid.Row="1"  
                    DisplayMode="CompactOverlay"  
                    OpenPaneLength="200"  
                    CompactPaneLength="52"  
                    HorizontalAlignment="Left">
            <SplitView.Pane>
                <ListBox SelectionMode="Single"  
                          Name="lbNavigator">
                    <ListBoxItem Name="lbiHomePage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE10F;" />
                            <TextBlock Text="Home" FontSize="20" Margin="20,0,0,2" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiEventPage">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/Assets/EventIcon.png" Height="Auto" Width="24" Margin="0,0,0,0" HorizontalAlignment="Left"></Image>
                            <TextBlock Text="Event" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiAboutPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE171;" />
                            <TextBlock Text="About" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiBuyPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE719;" />
                            <TextBlock Text="Buy" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                </ListBox>
            </SplitView.Pane>
            <SplitView.Content>
                <Frame Name="frmContent">
                </Frame>
            </SplitView.Content>
        </SplitView>
    </Grid>
</Page>

The XAML for the mobile’s MainPage is very similar. The risk with current approach is obliviously a lot of duplicated code, and I need to write more code before I really know the best way to design the views. A view per device family or many visual state triggers….

<Page
    x:Class="UWP.Prototype.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWP.Prototype.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.BottomAppBar>
        <CommandBar Name="cmdbarToolbar" RelativePanel.RightOf="btnNavigator">
            <AppBarButton Name="cmdbtnSave" Icon="Save"  Label="Save" />
            <AppBarButton Name="cmdbtnAdd" Icon="Add"  Label="Add" />
            <AppBarButton Name="cmdbtnEdit" Icon="Edit"  Label="Edit" />
            <AppBarButton Name="cmdbtnDelete" Icon="Delete" Label="Delete"/>
            <AppBarButton Name="cmdbtnCancel" Icon="Cancel"  Label="Cancel"/>
        </CommandBar>
    </Page.BottomAppBar>

    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <RelativePanel Grid.Row="0" Background="LightGray">
            <Button Name="btnNavigator" 
                    Background="LightGray"
                    FontFamily="Segoe MDL2 Assets" 
                    Content="&#xE700;" 
                    FontSize="24"
                    Margin="0,0,0,0"
                    Click="btnNavigator_Click"
                    RelativePanel.AlignLeftWithPanel="True"></Button>
        </RelativePanel>
        <SplitView Name="spvwNavigator"  
                    Grid.Row="1"  
                    DisplayMode="Overlay"  
                    OpenPaneLength="200"  
                    CompactPaneLength="56"  
                    HorizontalAlignment="Left">
            <SplitView.Pane>
                <ListBox SelectionMode="Single"  
                          Name="lbNavigator">
                    <ListBoxItem Name="lbiHomePage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE10F;" />
                            <TextBlock Text="Home" FontSize="20" Margin="20,0,0,2" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiEventPage">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/Assets/EventIcon.png" Height="Auto" Width="24" Margin="0,0,0,0" HorizontalAlignment="Left"></Image>
                            <TextBlock Text="Event" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiAboutPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE171;" />
                            <TextBlock Text="About" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiBuyPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE719;" />
                            <TextBlock Text="Buy" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                </ListBox>
            </SplitView.Pane>
            <SplitView.Content>
                <Frame Name="frmContent">
                </Frame>
            </SplitView.Content>
        </SplitView>
    </Grid>
</Page>

Transform XML in SQL Server 2005

In my current project one of the systems is used to manage files. The system is able to handle several different file types. Each file type has its own set of meta data. The meta data describes particular characteristics of each file and is stored as XML in the database. Example of meta data is File Type, Tool, Version and Release Information.

The customer wants to generate a description about the file from the meta data. Each file type has it own set of rules on how to generate the description. For example, the description for files of type Misc shall include File Type, Tool and Version. It shall be easy to change the content of a file description and not require a new release of the system.

An appealing solution is to use XSLT to transform the XML based meta data to a description. By storing the XSLT for each file type in the database, it would be easy to change file description during runtime. Since most information aggregation and querying happens in the database, it would be beneficially if we were able to generate the description in the database and use it different views. So how do we transform XML with XSLT in SQL Server 2005?

To solve this problem, I had to create utilities functions in C#, register the assembly in SQL server and to create a function that map one of the utility functions to SQL.

I created two utility functions in C#. One general purpose function used to transform XML with XSLT and one function that specifically is used to generate a file description.

The transform function takes a XML document and a XSLT style sheet and returns the resulting XML data from applying the style sheet on the document.

public static SqlXml Transform(SqlXml xmlData, SqlXml xsltData)

{

//Initialize

MemoryStream memoryXml = new System.IO.MemoryStream();

XslCompiledTransform xslt = new XslCompiledTransform();

// Load XSL transformation

xslt.Load(xsltData.CreateReader());

//Transform

System.IO.MemoryStream ms = new System.IO.MemoryStream();

xslt.Transform(xmlData.CreateReader(), null, ms);

ms.Seek(0, System.IO.SeekOrigin.Begin);

//Return the transformed value

SqlXml retSqlXml = new SqlXml(ms);

string tmp = retSqlXml.Value;

return (retSqlXml);

}

Since I wanted a string, I also created a specific function returning the description from a XML document. This function assumes that the file description is stored in tag called Description. It requires the XML document and XSLT style sheet, and returns the generated file description.

public static string GenerateDescription(string xmlData, string xsltData)

{

string description = “”;

//If missing input, return an empty string

if(string.IsNullOrEmpty(xmlData) | string.IsNullOrEmpty(xsltData))

{

return “”;

}

try

{

//Initialize

StringReader stringXmlReader = new StringReader(xmlData);

XmlReader xmlReader = new XmlTextReader(stringXmlReader);

SqlXml sqlXmlData = new SqlXml(xmlReader);

StringReader stringXsltReader = new StringReader(xsltData);

XmlReader xsltReader = new XmlTextReader(stringXsltReader);

SqlXml sqlXsltData = new SqlXml(xsltReader);

//Transform

SqlXml result = Transform(sqlXmlData, sqlXsltData);

//Get description

XmlDocument xmlDocument = new XmlDocument();

xmlDocument.LoadXml(result.Value);

description =xmlDocument.SelectSingleNode(“Description”).InnerText;

}

catch (Exception e)

{

//TODO: Determine error handling

description = “Error when generating description!”;

}

return description;

}

The assembly can be registered from SQL Server Management Studio Express or by a script. I used the following script to register my assembly.

CREATE ASSEMBLY [Company.CSSS.SqlServer]

AUTHORIZATION [dbo]

FROM ‘C:\Program Files\Company IT\Central System Supporting System\Company.CSSS.SqlServer.dll’

WITH PERMISSION_SET = SAFE

GO

Thereafter you need to enable the CLR. This can also be made from a script.

EXEC sp_CONFIGURE ‘show advanced options’ , ‘1’;

GO

RECONFIGURE;

GO

EXEC sp_CONFIGURE ‘clr enabled’ , ‘1’

GO

RECONFIGURE;

GO

The script that creates the function that maps the utility function to SQL looks like:

CREATE FUNCTION [dbo].[GetFileDescription](@xmlData [nvarchar](4000), @xsltData [nvarchar](4000))

RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER

AS

EXTERNAL NAME [Company.CSSS.SqlServer].[Company.CSSS.SqlServer.XsltTransformer].[GenerateDescription]

GO