HttpContext.Current.Session – Unit Testing

Here is a quick clever trick for failing over the connection string, in the case that it doesn’t already exist on the HttpContext.Current.Session object.

As you may know, Unit Testing frameworks don’t always mock out the HttpContext class properly, if at all.  This is unfortunate if you rely on objects stored there and you still want to unit test them.

string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnectionString"].ConnectionString;

try
{
    if (HttpContext.Current != null)
        if (HttpContext.Current.Session["ConnectionString"] != null)
            connectionString = HttpContext.Current.Session["ConnectionString"].ToString();

    using (var cn = new SqlConnection(connectionString))
   {
....

There are a lot of approaches to this problem, this is but one of them.

Hope this helps!

// Dave

Posted in Development | Tagged , | Leave a comment

My First Windows Phone 7 App

This will be a good way for me to document what I’m learning, while building my first “real” Windows Phone 7 app.

Background

My intent is to build a Personal Bartender app.

It will look something like this:

combined

What I’ve Done So Far

I’ve modified PanoramaBackground.png, ApplicationIcon.png, and Background.png that came as part of the Panorama Project Template.  With a touch of playing around in Paint.NET I had some images I was relatively happy with.

 

Next, I grabbed a listing of 175 common drink recipes, and converted it to an XML file I could play with.

image

 

I next created a new ViewModel to hold the drink recipes.  Drinks have a Name, and a collection of Ingredients, Instructions, and Comments.

    public class DrinkViewModel : INotifyPropertyChanged
    {
        private string _drinkName = string.Empty;
        private string _category = string.Empty;

        public DrinkViewModel()
        {
            Drinks = new ObservableCollection<DrinkViewModel>();
        }

        public ObservableCollection<DrinkViewModel> Drinks { get; set; }

        public string DrinkName
        {
            get { return _drinkName; }
            set
            {
                if (value != _drinkName)
                {
                    _drinkName = value;
                    NotifyPropertyChanged("DrinkName");
                }
            }
        }


        public ObservableCollection<string> Ingredients { get; set; }

        public string IngredientsFormatted
        {
            get
            {
                string result = string.Empty;
                if (Ingredients != null)
                    foreach (string ingredient in Ingredients)
                    {
                        result += ingredient + Environment.NewLine;
                    }
                return result;
            }
        }

        public string Category
        {
            get { return _category; }
            set
            {
                if (value != _category)
                {
                    _category = value;
                    NotifyPropertyChanged("Category");
                }
            }
        }

        public ObservableCollection<string> Instructions { get; set; }

        public string InstructionsFormatted
        {
            get
            {
                string result = string.Empty;
                if (Instructions != null)
                    foreach (string instruction in Instructions)
                    {
                        result += instruction + Environment.NewLine;
                    }
                return result;
            }
        }

        public ObservableCollection<string> Comments { get; set; }

        public string CommentsFormatted
        {
            get
            {
                string result = string.Empty;
                if (Comments != null)
                    foreach (string comment in Comments)
                    {
                        result += comment + Environment.NewLine;
                    }
                return result;
            }
        }

        public bool IsDataLoaded { get; private set; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;


        #endregion

        public void LoadData()
        {
            using (XmlReader reader = XmlReader.Create("drinks.xml"))
            {
                while (reader.Read())
                {
                    if (reader.IsStartElement())
                    {
                        if (reader.IsEmptyElement)
                            Console.WriteLine("<{0}/>", reader.Name);
                        else
                        {
                            Console.Write("<{0}> ", reader.Name);
                            reader.Read(); // Read the start tag.

                            if (reader.IsStartElement()) // Handle nested elements.
                                Console.Write("\r\n<{0}>", reader.Name);
                            string drinkName = reader.GetAttribute("Name");
                            if (!String.IsNullOrEmpty(drinkName))
                                Drinks.Add(new DrinkViewModel { DrinkName = drinkName });
                            Console.WriteLine(drinkName); //Read the text content of the element.
                        }
                    }
                    else
                    {
                        Console.Write("<{0}> ", reader.Name);
                        reader.Read(); // Read the start tag.

                        if (reader.IsStartElement()) // Handle nested elements.
                            Console.Write("\r\n<{0}>", reader.Name);

                        var drink = new DrinkViewModel();
                        string drinkName = reader.GetAttribute("Name");
                        string ingredient = string.Empty;

                        if (!String.IsNullOrEmpty(drinkName))
                        {
                            XmlReader readerSubtree = reader.ReadSubtree();

                            while (readerSubtree.Read())
                            {
                                if (readerSubtree.Name == "Ingredient")
                                {
                                    ingredient = readerSubtree.GetAttribute("Ingredient");

                                    if (drink.Ingredients == null)
                                        drink.Ingredients = new ObservableCollection<string>();

                                    if (ingredient != null && !ingredient.Contains("Category:"))
                                        drink.Ingredients.Add(ingredient);

                                    if (ingredient != null && ingredient.Contains("Category:"))
                                    {
                                        drink.Category = ingredient.Substring(9);
                                    }
                                }
                            }

                            drink.DrinkName = drinkName;
                            Drinks.Add(drink);
                        }

                        Console.WriteLine(drinkName);
                    }
                }
            }

            IsDataLoaded = true;
        }

        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

 

Binding this content to the MainPage.xaml is also a pretty quick task.  I simply adjusted the StackPanel and added some additional TextBlocks.

<controls:PanoramaItem Header="Recent">
    <!--Double line list with text wrapping-->
    <ListBox Margin="0,0,-12,0"
             ItemsSource="{Binding Drinks}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="0,0,0,17"
                            Width="432">
                    <TextBlock Text="{Binding DrinkName,Mode=OneTime}"
                               TextWrapping="Wrap"
                               Style="{StaticResource PhoneTextExtraLargeStyle}" />
                    <TextBlock Text="{Binding Category, Mode=OneTime}"
                               TextWrapping="Wrap"
                               Foreground="Yellow"
                               Style="{StaticResource PhoneTextSmallStyle}" />
                    <TextBlock Text="{Binding IngredientsFormatted, Mode=OneTime}"
                               TextWrapping="Wrap"
                               Style="{StaticResource PhoneTextSmallStyle}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</controls:PanoramaItem>

 

The result is that I now have a scrollable list of drinks, with their recipes.

realdrinks

Next Steps

I need to add a new Windows Phone Page so that when the user selects a drink, they can view the complete details.  Naturally this needs to work with the back button as well.

 

So far, so good.  Windows Phone development is fun!

// Dave

Posted in Development | Tagged , | 2 Comments

Cannot Freakin’ Wait for Windows Phone 7!

728x90_Banner_WP7DevLaunch

I already have some great ideas!

// Dave

Posted in Development | Tagged | Leave a comment

Incredibly Useful Developer Tools

These are some tools I have a hard time living without.

Syntevo SmartSVN

JetBrains Resharper

SourceGear DiffMerge

Silverlight Spy

Notepad++

Fiddler2

HttpWatch

RedGate ANTS Profiler

WinRar

// Dave

Posted in Development | Tagged , , | 1 Comment

Getting Useful Error Messages out of Silverlight

Step 1: Change the default behavior of WebRequest errors goes to the ClientHttp stack instead of the default browser handling.

 

// Tell Silverlight that the ClientHttp stack should be used.
// This let's us get more detailed exceptions from our service vs. the default Browser handling of errors. (401 Not Found)
// http://msdn.microsoft.com/en-us/library/system.net.webrequest.registerprefix.aspx
// http://msdn.microsoft.com/en-us/library/dd920295(VS.95).aspx
bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
bool httpsResult = WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);

Step 2: Change the global exception handling in Silverlight so that the actual exception messages bubble up to a custom ChildWindow (in this case, it’s called ErrorWindow).

 

/// <summary>
/// Occurs for all unhandled exceptions.  Launches the /Views/ErrorWindow.xaml page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
    // If the app is running outside of the debugger then report the exception using
    // the browser's exception mechanism. On IE this will display as a yellow alert 
    // icon in the status bar and Firefox will display a script error.
    if (!Debugger.IsAttached)
    {
        // NOTE: This will allow the application to continue running after an exception has been thrown
        // but not handled. 
        // For production applications this error handling should be replaced with something that will 
        // report the error to the website and stop the application.
        e.Handled = true;
        //Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
        var error = new ErrorWindow(e.ExceptionObject.InnerException.Message.ToString() + Environment.NewLine
             + e.ExceptionObject.InnerException.StackTrace);
        error.Show();
    }
}

 

Step 3: Update your web.config so that includeExceptionDetailsInFaults is true.

 

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="LLServiceBehavior">
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true"/>
                <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

Step 4: Test it by throwing an exception in your web service.

 

 throw new ArithmeticException("Check me out!");

 

clip_image002

 

Hope this helps!

 

// Dave

Posted in Development | Tagged | 1 Comment

Silverlight–Quickly Enable / Disable All Buttons

Here is some clever code to Enable or Disable all buttons on a Silverlight page.

 

 

/// <summary>
/// Bulk disable / enable all of the buttons on the UI
/// </summary>
/// <param name="isEnabled"></param>
public void EnableDisableButtons(bool isEnabled)
{
    var buttons = GetButtonControls(LayoutRoot).OfType<Button>();
    foreach (var btn in buttons)
    {
        btn.IsEnabled = isEnabled;
    }
}

/// <summary>
/// Return all button controls on the page
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
private static IEnumerable<DependencyObject> GetButtonControls(DependencyObject root)
{
    var doList = new List<DependencyObject> { root };
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
        doList.AddRange(GetButtonControls(VisualTreeHelper.GetChild(root, i)));
    return doList;
}
Posted in Development | Tagged | 2 Comments

Silverlight XAML Designer– Making files open faster in Visual Studio 2010

This little tip is probably all over the place, but just in case:

When you open a xaml file, the Visual Studio 2010 designer is also loaded, which can take significant time.

If all you’re doing is messing with the xaml manually (rather than dragging things around the design surface), here is how you turn the designer off:

Tools | Options | Text Editor | XAML | Miscellaneous

image

John Stockton gave me that little tip, and it’s definitely sped things up.

 

Hope this helps!

// Dave

Posted in Development | Tagged | 3 Comments

Passing Values between Pages in a Silverlight 4 Navigation Application

Often you’ll want to pass selected values from one page in a Silverlight 4 application to another.

Query Strings are a valid approach, but you might want to pass more than simple strings or IDs in the URL.

This quick walkthrough will show you to use access a simple static variable from one page, on another.  This could easily be a full object, but in this example it will just be a string.

 

Start off by creating a new project.  Silverlight now ships with a “Silverlight Navigation Application” template, which is useful for creating Line of Business (LOB) applications.  There are also a number of other templates, such as the Cosmopolitan Theme that you might find useful.

image

Once the project is created, open Home.xaml.cs and add a static variable to Home.xaml.cs.  This is the value we’ll be reading back on the next page.

public partial class Home : Page
{
    public static string ValueFromHome = 
        "A Value on the Home.xaml.cs page";

Now add a new Page, using Page1.xaml as the default name.

image[20]

We need a way to navigate here, so add a Button to Home.xaml.

 

<navigation:Page x:Class="SLNavDemo.Home" 
    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:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
    Title="Home"
    Style="{StaticResource PageStyle}">

    <Grid x:Name="LayoutRoot">
        <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">

            <StackPanel x:Name="ContentStackPanel">

                <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" 
                                   Text="Home"/>
                <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}" 
                                   Text="Home page content"/>

                <Button Name="btnGoToPage1" Content="Go to Page 1"
                        Click="btnGoToPage1_Click"/>
                
            </StackPanel>

        </ScrollViewer>
    </Grid>

</navigation:Page>

 

Utilizing the NavigationService, add the following content to the Click Event.  Notice the relative URI for /Page1.  We don’t have to specify the full file name for the page, since the Navigation service can figure this out for us using UriMappings.

private void btnGoToPage1_Click(object sender, RoutedEventArgs e)
{
    this.NavigationService.Navigate(new Uri("/Page1", UriKind.Relative));
}

 

If you’re curious how this works, you can view the UriMappings in MainPage.xaml.  The last UriMapping simply says “if the page isn’t mapped explicitly, just try to find a file in the /Views folder with a .xaml extension.

 

<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}" 
                  Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed">
    <navigation:Frame.UriMapper>
      <uriMapper:UriMapper>
        <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
        <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
      </uriMapper:UriMapper>
    </navigation:Frame.UriMapper>
</navigation:Frame>

 

Now open Page1.xaml and add a simple TextBlock to the page.

<navigation:Page x:Class="SLNavDemo.Views.Page1" 
           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"
           mc:Ignorable="d"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           d:DesignWidth="640" d:DesignHeight="480"
           Title="Page1 Page">
    <Grid x:Name="LayoutRoot">
        <TextBlock Name="tb" />
    </Grid>
</navigation:Page>

 

Now all we have to do is update the Text property, with the value from the Home page.

        public Page1()
        {
            InitializeComponent();

            tb.Text = Home.ValueFromHome;
        }

 

Hit F5 to run.

 

Click the button we added, and the application will navigate to Page1, with the text applied.

image

 

image

You’ll also notice that the URL changed to /Page1.  This is to support the browsers back button.

A pretty simple example, but this can be powerful when passing along values from one page to another, for instance, selected items in a grid.  You can also use this approach to reduce extra web service calls, if the values already exist on another page in the Silverlight application that the user has interacted with.

Hope this helps!

// Dave

Posted in Development | Tagged | 11 Comments

Silverlight Resources

Defining Resources

In Silverlight you can define resources, which will be available to the rest of the application.  You can define these resources at the top of your user controls, in your pages, App.xaml, or in separate ResourceDictionaries.

App.xaml is usually a good place to put the bulk of all style elements.  For Silverlight, this includes not only fonts and colors, but also animations (storyboards), convertors, and the like.

It’s a good idea to use a single defined font throughout the application.

In this example it’s named “MainFont”, which is made of Tahoma, Verdana, and Arial.  Just like CSS, if one font is unavailable, it moves to the next.  Fortunately, all 3 are built-in Silverlight fonts.

 <FontFamily x:Key="MainFont">Tahoma, Verdana, Arial</FontFamily>

The next piece to understand is the difference between “brushes” and “styles”.

A Brush, like this, represents the color gray.

 <SolidColorBrush x:Key="GrayButtons"
                  Color="#FF5C5A67" />

Now a Style is something that affects other controls throughout the application.  Here is one that affects all TextBlocks:

<Style TargetType="TextBlock">
    <Setter Property="FontFamily"
            Value="{StaticResource MainFont}" />
    <Setter Property="Foreground"
            Value="{StaticResource GrayButtons}" />
    <Setter Property="FontWeight"
            Value="Normal" />
    <Setter Property="FontSize"
            Value="10.667" />
</Style>

You can read the above as saying “for any TextBlock control that does not have a specific styling specified, use MainFont and GrayButtons.  Make the FontWeight Normal, and not Bold, and set the default FontSize to 10.667”.

Styles cascade in Silverlight, much like CSS.  So the App.xaml is the first set of Styles to be defined.  Controls within the application may override these styles to set properties like Font Weight or Font Size, but for the most part, this file includes the Styling for the application.

If you’re still with me, I’ll throw out just two more quick things:

  • · When you style a Telerik control, the design tools automatically define every property available for that Telerik control, including animations (storyboards).  This is a great way to end up with a ton of content in a single file…
  • · If you download the trial version of Microsoft Expression Blend 4, you’ll be able to open and navigate the App.xaml file and actually see the styles.

image

Utilizing Resources

There are two basic ways to utilize the Resources you’ve defined.

The preferred way is to reference them directly in xaml like this:

<TextBlock Foreground="{StaticResource GrayButtons}"
           Text="Some Text"
           x:Name="txtSomeText"
           FontSize="10.667"
           FontFamily="{StaticResource MainFont}" />

This has the added benefit of supporting Designers, who will be likely be familiar with Expression Blend.

Another way is to reference them directly in code.  For Resources stored in App.xaml, you would use the following syntax:

SolidColorBrush titleTextBrush = App.Current.Resources["GrayButtons"] as SolidColorBrush;

 

Hope this helps, let me know if you have any questions!

// Dave

Posted in Development | Tagged | Leave a comment

Displaying the Assembly Version # from a Silverlight 4 App

Assembly assembly = Assembly.GetExecutingAssembly();
String version = assembly.FullName.Split(',')[1];
String fullversion = version.Split('=')[1];

int build = int.Parse(fullversion.Split('.')[2]);
int revision = int.Parse(fullversion.Split('.')[3]);
DateTime buildDate = new DateTime(2000, 1, 1).AddDays(build).AddSeconds(revision * 2);
String fulldate = buildDate.ToLocalTime().ToString(CultureInfo.InvariantCulture);

txtAssemblyVersion.Text = fullversion
    + Environment.NewLine + buildDate.ToShortDateString() + " " + buildDate.ToShortTimeString();

It’s just that easy!

// Dave

Posted in Development | Tagged | 1 Comment