Thursday, July 29, 2010

Clearable TextBox Custom Control

After some comments from Laurent Bugnion, of Galasoft and MVVM Light fame, I decided to try my hand at turning this simple little Clearable TextBox into a custom control for better "Skinability".







It looks like I've got most of the functionality replicated, including adding two states to help with animations.  The states are "Normal" and "Cleared".  By default, the Cleared state will cause the clear button text to flash red briefly.  You can also now set the ClearButtonTemplate and the ClearButtonContent if you want.  In the picture you can see I've set the ClearButtonContent to Clear and used the default template.



<clr:ClearableTextBox  
    Text="{Binding SomeText, Mode=TwoWay}"
    ClearButtonContent="Clear"
    VerticalAlignment="Top"/>




I haven't tested any custom state animations, only the default ones that are included.  Feel free to let me know if you find any problems. The source and binaries are available below.



Clearable TextBox Custom Control Source



Now Playing: The Roots - Don't Say Nuthin

Wednesday, July 28, 2010

A Clearable TextBox for Win Phone 7

Update: I've updated this UserControl to a Custom Control for better templating and posted it for download. Check it out in the Clearable TextBox Custom Control post.



After seeing a tweet about the lack of a clearable text box similar to the IPhone by Eric Malamisura, I was inspired to whip together a simple control that fills this need.






Here is some code for the control, in case you don't want to download the full example. Just create a new UserControl called ClearableEditBox and paste these parts in the relevant places.



<!-- Put inside your new UserControl -->
<Grid x:Name="LayoutRoot">
    <TextBox
        MinWidth="50"
        Text="{Binding ElementName=uiThis, Path=Text, Mode=TwoWay}"
        x:Name="editBox"/>
        
    <Button
        MinWidth="30"
        HorizontalAlignment="Right"
        VerticalAlignment="Center"
        Click="clrBtn_Click"
        x:Name="clrBtn">
        <Button.Template>
            <ControlTemplate>
                <TextBlock                                
                    FontSize="25"            
                    Margin="0 0 20 0"
                    Foreground="Gray"            
                    FontWeight="Bold"
                    Text="X"/>
            </ControlTemplate>
        </Button.Template>
    </Button>
</Grid>

// Put inside your code behind for your new UserControl.
public partial class ClearableTextBox : UserControl, INotifyPropertyChanged
{
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for EditText.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(ClearableTextBox), new PropertyMetadata(string.Empty, HandleTextChanged));        

    public ClearableTextBox()
    {
        InitializeComponent();
    }

    private static void HandleTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        var box = obj as ClearableTextBox;
        if (null != box)
            box.OnPropertyChanged("Text");
    }

    private void clrBtn_Click(object sender, RoutedEventArgs e)
    {
        Text = string.Empty;
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string name)
    {
        if (null != PropertyChanged)
            PropertyChanged(null, new PropertyChangedEventArgs(name));
    }

    #endregion
}




You can also download a sample project containing the control here.




Clearable TextBox UserControl



Now Playing: Eminem - Airplanes

Monday, July 26, 2010

Updated Win Phone 7 Busy Service That Does Not Change RootVisual

Evidently, you are not supposed to change the RootVisual in a Win Phone 7 application.  There was a forum post posed by Matt Hidinger and answered by Peter Torr about Changing the RootVisual that indicates this might cause problems during the approval process.


As a result, I've updated my sample to not require wrapping the root level PhoneApplicationFrame with a Grid.  It turns out, most pages already have a Grid as their LayoutRoot element and you can just pass this in to a new RootPaneBusyService and use it in the same manner.  So instead of passing the App.Current.RootVisual as Grid, we pass the LayoutRoot.

protected override void OnNavigatedTo( System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            
            var busyServ = new RootPanelBusyService(this.LayoutRoot);
            this.DataContext = new MainPageVM(busyServ);            
        }

I've also updated the CreateBusyElement method to detect how many rows and columns are in the passed in root visual and set the ColumnSpan and RowSpan accordingly.

// Set the row and column span's if the root is a grid.
            if (rootVisual is Grid)
            {
                var gridRoot = rootVisual as Grid;

                int rowSpan = 1;
                if (gridRoot.RowDefinitions != null)
                    rowSpan = gridRoot.RowDefinitions.Count + 1;
                int columnSpan = 1;
                if (gridRoot.ColumnDefinitions != null)
                    columnSpan = gridRoot.ColumnDefinitions.Count + 1;

                Grid.SetRowSpan(root, rowSpan);
                Grid.SetColumnSpan(root, columnSpan);
            }

Download the updated sample



Create a Win Phone 7 Busy Service with Loady animation

Update: It looks like there may be a problem with wrapping the RootFrame in a Grid, but I haven't found a good answer to why.  Check this Win Phone 7 Forum Post about Changing the RootVisual.



Update 2: I've updated my example to not require changing the RootVisual.  But you will still need to have a Grid as the Root of your Page.  Check out the Updated Busy Service.



I've been spending a lot of time working on data driven Win Phone 7 apps in the past couple weeks and one of the most useful things I've created is a simple Busy Service for Win Phone 7 apps.


The Busy Service lets you signal that something is busy, like when retrieving data from a web service or doing a long running calculation. Here is a look at it's interface;

/// <summary>
/// An interface for busy services.
/// </summary>
public interface IBusyService
{
bool IsBusyShown { get; }

void ShowBusy(string message);
void ShowBusy(TimeSpan timeToShow, string message);
void ShowBusy(double milliSecondsToShow, string message);

void HideBusy(double millisecondsToWait);
void HideBusy(TimeSpan delay);
void HideBusy();
}



I decided to implement a RootPanelBusyService, which basically means that it expects a "Panel" type of element, a Grid for example, at the RootVisual. The problem with the Win Phone 7 Beta update is that the RootVisual is no longer defined in the App.Xaml, so it would seem like you can't just wrap the Root level Phone Application Frame in a Grid. It turns out, it just takes a little more work, if you open up the App.xaml.cs and take a look at the CompleteInitializePhoneApplication method you will see where the RootVisual is assigned. So with a little code we can add a Grid wrapper around the PhoneApplicationFrame and have a nice place to add our Busy Loady icon.

// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
{
// Add a Grid wrapper around the Root application frame.
var root = new Grid();
root.Children.Add(RootFrame);

RootVisual = root;
}

// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}



Now that we have our Grid at the Root, we can instantiate a RootPanelBusyService and pass it to our ViewModel to start "Getting Busy...".

// From MainPage.xaml.cs
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);

if (App.Current.RootVisual is Grid)
{
var busyServ = new RootPanelBusyService(App.Current.RootVisual as Grid);
this.DataContext = new MainPageVM(busyServ);
}
}

// In our MainPage View Model (MainPageVM.cs)
/// <summary>
/// A view model for the Main Page.
/// </summary>
public class MainPageVM : ViewModelBase
{
/// <summary>
/// The busy service to use...
/// </summary>
private IBusyService busyService;

/// <summary>
/// Gets or sets the do busy command.
/// </summary>
/// <value>The do busy command.</value>
public ICommand DoBusy { get; private set; }

public MainPageVM(IBusyService busyServ)
{
busyService = busyServ;

DoBusy = new DelegateCommand&lt;object>(HandleDoBusy);
}

/// <summary>
/// Handles the do busy command.
/// </summary>
/// <param name="arg">Unused.
private void HandleDoBusy(object arg)
{
busyService.ShowBusy(2000, "Getting Busy...");
}
}


And there you have it, you've got a simple and easy to use busy service for your long running operations. One other trick that I occasionally use it to set a Busy Service static property on my App class, so all ViewModels have easy access to it. To do this, just add a static property to your App class, and assign it after setting the RootVisual, like so:

// Easy access to the busy service.
public static IBusyService BusyService { get; private set; }

// Rest of this class omitted for brevity....

// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
{
// Add a Grid wrapper around the Root application frame.
var root = new Grid();
root.Children.Add(RootFrame);

RootVisual = root;

// Set our easy access busy service property.
BusyService = new RootPanelBusyService(root);
}

// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}


If you don't want to download the full example project to get the RootPanelBusyService implementation, here is the source, but you'll need to create your own Loady graphic / control.

/// &lt;summary>
/// An interface for busy services.
/// </summary>
public interface IBusyService
{
bool IsBusyShown { get; }

void ShowBusy(string message);
void ShowBusy(TimeSpan timeToShow, string message);
void ShowBusy(double milliSecondsToShow, string message);

void HideBusy(double millisecondsToWait);
void HideBusy(TimeSpan delay);
void HideBusy();
}

/// <summary>
/// A busy service that expects a Panel / Grid as the root visual.
/// </summary>
public class RootPanelBusyService : IBusyService
{
private UIElement currentBusyElement;
private Panel rootVisual;

/// <summary>
/// Initializes a new instance of the &lt;see cref="RootPanelBusyService"> class.
/// </see></summary>
/// The root visual element.
public RootPanelBusyService(Panel rootVisualElement)
{
rootVisual = rootVisualElement;
}

#region IBusyService Members

private bool _busyShown = false;
public bool IsBusyShown
{
get { return _busyShown; }
}

public void ShowBusy(double milliSecondsToShow, string message = "Loading...")
{
ShowBusy(TimeSpan.FromMilliseconds(milliSecondsToShow), message);
}

public void ShowBusy(TimeSpan timeToShow, string message = "Loading...")
{
ShowBusy(message);

ThreadPool.QueueUserWorkItem(new WaitCallback(time =>
{
Thread.Sleep((TimeSpan)time);

// Hide the busy after a sleep.
rootVisual.Dispatcher.BeginInvoke(() => HideBusy());
}), timeToShow);
}

public void ShowBusy(string message = "Loading...")
{
_busyShown = true;
var busyEl = CreateBusyElement(message);
busyEl.Opacity = 0;

try
{
if (rootVisual is Panel)
{
var root = rootVisual;
root.Children.Add(busyEl);

var anim = CreateAnimation(busyEl, Grid.OpacityProperty, 0.8, 0.00, 900, EasingMode.EaseOut);

var story = new Storyboard();
story.Children.Add(anim);
story.Begin();
}
}
catch
{
Debug.WriteLine("Problem showing busy.");
}

currentBusyElement = busyEl;
}

public void HideBusy(double milliseconds)
{
HideBusy(TimeSpan.FromMilliseconds(milliseconds));
}

public void HideBusy(TimeSpan delay)
{
var root = rootVisual;
ThreadPool.QueueUserWorkItem(new WaitCallback((arg) =>
{
Thread.Sleep(delay);

((Panel)arg).Dispatcher.BeginInvoke(() =>
{
HideBusy();
});
}), root);
}

public void HideBusy()
{
try
{
if (rootVisual is Panel)
{
var root = rootVisual;
var anim = CreateAnimation(currentBusyElement, Grid.OpacityProperty, 0.00, .80, 1000, EasingMode.EaseOut);

var story = new Storyboard();
story.Children.Add(anim);
story.Begin();

// Remove the element a second later; I do it this way because StoryCompleted is flaky.
ThreadPool.QueueUserWorkItem(new WaitCallback(obj =>
{
Thread.Sleep(900);

root.Dispatcher.BeginInvoke(() =>
{
root.Children.Remove(currentBusyElement);

currentBusyElement = null;
});
}), null);                  
}
}
catch
{
Debug.WriteLine("Problem hiding busy.");
}

_busyShown = false;
}

#endregion


/// <summary>
/// Creates the busy element; A Loady with a text block underneath.
/// </summary>
/// The message to show below the loady.      
private UIElement CreateBusyElement(string message = "Loading...")
{
// create a grid to hold the loady and swallow the entire screen.
var root = new Grid()
{
Background = new SolidColorBrush(Colors.Black)
};

// The spinny loady thingy...
root.Children.Add(new Loady()
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
});

// The text below the loady...
root.Children.Add(new TextBlock()
{
Text = message,
Margin = new Thickness(0, 150, 0, 0),
FontSize = 30,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = System.Windows.VerticalAlignment.Center,
Foreground = new SolidColorBrush(Colors.White)
});

return root;          
}

/// <summary>
/// A helper method for creating double animations.
/// </summary>
public DoubleAnimation CreateAnimation(DependencyObject obj, DependencyProperty prop, double value, double milliseconds, EasingMode easing = EasingMode.EaseOut)
{
var from = Convert.ToDouble(obj.GetValue(prop));
return CreateAnimation(obj, prop, value, from, milliseconds, easing);
}

/// <summary>
/// A helper method for creating double animations.
/// </summary>
public DoubleAnimation CreateAnimation(DependencyObject obj, DependencyProperty prop, double value, double from, double milliseconds, EasingMode easing = EasingMode.EaseOut)
{
CubicEase ease = new CubicEase() { EasingMode = easing };
DoubleAnimation animation = new DoubleAnimation
{
Duration = new Duration(TimeSpan.FromMilliseconds(milliseconds)),
From = from,
To = value,
FillBehavior = FillBehavior.HoldEnd,
EasingFunction = ease
};
Storyboard.SetTarget(animation, obj);
Storyboard.SetTargetProperty(animation, new PropertyPath(prop));

return animation;
}
}




Now Playing: The Roots - Get Busy

Monday, July 19, 2010

Authenticating MVC 2 JSON Services from Win Phone 7 with OAuth Lite


One of the challenges I've been facing with using an ASP.Net MVC 2 site to return JSON data to my Win Phone 7 app is authenticating my requests. I don't want other people to be able to sniff on the data between my app and the server and start making malicious requests.


I started looking into a custom AuthorizeAttribute after spending most of last week looking into OAuth authentication methods for the FatSecret.com API service wrappers. If you're not familiar with OAuth, take a minute to read up on it.


I decided that I wasn't going to use the full OAuth authentication strategy, specifically, I boiled it down to three parameters and an HMACSH1 Hashed Signature. Basically, my signature format is this {HTTPMethod}&{ServiceURL}&{LimitedParmString}. Where my LimitedParmString consists of a standard OAuth "Nonce", a Timestamp (seconds from Jan 1, 1970 UTC), and your consumer key. My client (a Win Phone 7 app in this case) includes this signature as a request header called "oauthlite" when they make their service requests to the MVC Website.


On the server side, my custom AuthorizeAttribute named OAuthLiteAuthenticate takes the HTTPContextBase and constructs a signature based on a request header called "oauthlite". The custom request header is just a url encoded parameter string with the 4 parameters; the "Nonce", Timestamp, Consumer Key and Signature Hash computed by the requestor.


Here is an example "oauthlite" header:



You can get the gist of the authentication process by taking a look at this in-memory implementation of an OAuthLiteAuthenticator:




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace OAuthLite.Server
{
/// <summary>
/// An in memory OAuthLite Authenticator example.
/// </summary>
public class OAuthLiteDictionaryAuthenticator : IOAuthLiteAuthenticator
{
// An "in-memory" key repository.
private Dictionary<string, string> _keyRepository = new Dictionary<string, string>()
{
// We only have one client, but you could add more.
{ "8b84444fbc09448da68ca14f000695cb", "83fbf4ea05df427bb3390d6d9a0fc626" }
};

private static string UrlFormat = "{0}://{1}";

#region IOAuthLiteAuthenticator Members

public bool Authenticate(HttpContextBase context)
{
if (context == null
|| context.Request == null)
return false;

var requestUrl = context.Request.Url;

var apiUrl = String.Format(UrlFormat, requestUrl.Scheme, requestUrl.Host);
var method = (HttpMethod)Enum.Parse(typeof(HttpMethod), context.Request.HttpMethod.ToUpper());

var header = context.Request.Headers["oauthlite"];

// We expect a parmstring including the signature.
if (String.IsNullOrEmpty(header)
|| !header.Contains("&"))
return false;

Dictionary<string, string> parms = new Dictionary<string, string>();
foreach (var parm in header.Split('&'))
{
string[] s = parm.Split('=');
if (s.Length < 2)
continue;

parms.Add(s[0], s[1]);
}

if (!parms.ContainsKey("signature") || !parms.ContainsKey("key"))
return false;

var signature = HttpUtility.UrlDecode(parms["signature"]);
parms.Remove("signature");

var key = parms["key"];

var secret = GetSecretByKey(key);

if ( string.IsNullOrEmpty(secret) )
return false;

return OAuthLiteHelper.ValidateSignature(signature, method, apiUrl, secret, parms);
}

private string GetSecretByKey(string key)
{
if (!_keyRepository.ContainsKey(key))
return null;

return _keyRepository[key];
}

#endregion
}
}



I've updated the Win Phone 7 JSON Services code example to use the new OAuthLiteAuthenticate attribute on an action called "Secrets" on the Product Controller. You can download the example below.




Download the code





Now Playing: Foals - Spanish Sahara


Tuesday, July 13, 2010

Data Driven Win Phone 7 Apps With MVC 2 JSON Services




I've been making a lot of little apps for Win Phone 7 in the past couple of weeks and I want to share a little bit of my code for other people who might be starting out and looking for some examples of creating a data driven Windows Phone 7 app.


We are going to be making a simple little product search for a fake company. We are going to show POSTing information to an MVC Controller action from our Win Phone 7 app, and we are going to show parsing a JSON response received from our MVC site and displaying it on the screen.


MVC 2 Website



The first thing I do when I'm creating a strictly service oriented site is to modify the Site.Master page to not display the login control, or the About page. I also, exclude the Account LogOn, Register and ChangePassword views so no one is tempted to register for the site. This step is optional, you can leave all of those things in, and you probably will have to if you have an existing MVC site you are altering.


Next, I create a new controller to serve my data. For our example we will call it ProductController and it will look something like this.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace WinPhone7.MVCExample.Website.Controllers
{
public class ProductInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

public interface IProductService
{
IQueryable<ProductInfo> GetProducts(Predicate<ProductInfo> filter);
void AddProduct(ProductInfo newProduct);
}

// This is dirty... but it's a demo
public static class ProductRepository
{
// An In-Memory persistable list of products.
public static List<ProductInfo> Products = new List<ProductInfo>()
{
new ProductInfo()
{
Id = 1,
Name = "Product 1",
Description = "Some sample product that is related to toys"
},
new ProductInfo()
{
Id = 2,
Name = "Product 2",
Description = "Some sample product that is related to sports"
},
new ProductInfo()
{
Id = 3,
Name = "Product 3",
Description = "Some sample product that is related to cars"
},
new ProductInfo()
{
Id = 4,
Name = "Product 4",
Description = "Some sample product that is related to boats"
},
new ProductInfo()
{
Id = 5,
Name = "Product 5",
Description = "Some sample product that is related to tools"
},
new ProductInfo()
{
Id = 6,
Name = "Product 6",
Description = "Some sample product that is related to technology"
},
};
}

public class MockProductService : IProductService
{
public IQueryable<ProductInfo> GetProducts(Predicate<ProductInfo> filter)
{
return ProductRepository.Products
.Where(prod => filter(prod))
.AsQueryable();
}

public void AddProduct(ProductInfo newProduct)
{
newProduct.Id = ProductRepository.Products.Count + 1;
ProductRepository.Products.Add(newProduct);
}
}

public class ProductSearchRequest
{
public string SearchTerm { get; set; }
}

public class ProductListResponse
{
public List<ProductInfo> Matches { get; set; }
}

public class ProductSearchResponse : ProductListResponse
{ }

public class ProductAddResponse
{
public bool Success { get; set; }
public int Id { get; set; }
}

public class ProductController : Controller
{
IProductService _products;

public ProductController()
: this(new MockProductService()) // Lazy man's dependency injection.
{

}

public ProductController(IProductService productServ)
{
_products = productServ;
}

public ActionResult All()
{
// Get all products by passing true predicate.
var allProducts = _products.GetProducts(prod => true);

var response = new ProductListResponse()
{
Matches = allProducts.ToList()
};

return new JsonResult()
{
// Make sure we allow get's
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
// Set the data to our response.
Data = response
};
}

public ActionResult Search(ProductSearchRequest request)
{
var termLowered = request.SearchTerm.ToLower();
var matches = _products
.GetProducts(prod =>
prod.Name.ToLower().Contains(termLowered)
|| prod.Description.ToLower().Contains(termLowered));

var response = new ProductSearchResponse()
{
Matches = matches.ToList()
};

return new JsonResult()
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = response
};
}

[HttpPost]
public ActionResult Add(ProductInfo product)
{
ProductAddResponse response;
if (!String.IsNullOrEmpty(product.Name)
&& !String.IsNullOrEmpty(product.Description))
{
_products.AddProduct(product);

response = new ProductAddResponse()
{
Success = true,
Id = product.Id
};
}
else
response = new ProductAddResponse()
{
Success = false,
Id = -1
};

return new JsonResult()
{
Data = response
};
}
}


I've included the response and request classes in the code example for brevity, but I usually separate these out into files in the models folder. Once we have our products controller in place, we can go ahead and run the website and see some results. Hit F5 to run the MVC Website, then navigate to /Product/All to see your example JSON response (I highly recommend Google Chrome and this JSON Content Viewer, makes the JSON all color coded and nice).


Win Phone 7 Services



Next, I go ahead and create my Services project as a Win Phone 7 class library. Now, I've written some helper classes to deal with requesting web content and parsing JSON results. I've included it in the Sample Code as a library called Service4u2. The meat and potatoes of this library is the BaseJsonService class. This will save you tremendous amounts of work for consuming JSON services. Here is what a basic Product Search JSON Service looks like (I've included out specific app's URL Helper for brevity).



using System.Collections.Generic;
using Service4u2.Json;

namespace WinPhone7.MVCExample.Client.Services
{
// Extra stuff included for brevity.
public class ProductInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

public class ProductSearchRequest
{
public string SearchTerm { get; set; }
}

public class ProductListResponse
{
public List<ProductInfo> Matches { get; set; }
}

public class ProductSearchResponse : ProductListResponse
{ }

public class ProductAddResponse
{
public bool Success { get; set; }
public int Id { get; set; }
}

public static class ExampleUrlHelper
{
// Singleton pattern url helper.

private static ServiceUrlHelper _helper =
new ServiceUrlHelper("http://localhost.:49709");

public static ServiceUrlHelper Instance { get { return _helper; } }
}

// Product List Service.
public class ProductListService : BaseJsonService<ProductListResponse>
{
public void GetProductListAsync()
{
var url = ExampleUrlHelper
.Instance
.GetControllerActionParameterUrl("Product", "All", string.Empty);

StartServiceCall(url);
}
}

// Product Search Service.
public class ProductSearchService : BaseJsonService<ProductSearchResponse>
{
// We have to wrap our request so it is URL encoded properly for MVC.
// Our Product/Search action expects a parameter named request.
public class SearchRequestWrapper
{
public ProductSearchRequest request { get; set; }
}

public void SearchProductsAsync(ProductSearchRequest searchRequest)
{
var url = ExampleUrlHelper
.Instance
.GetControllerActionParameterUrl("Product", "Search", string.Empty);

var postData = new SearchRequestWrapper()
{
request = searchRequest
}.Postify(); // Postify our data, e.g. request.SearchTerm=blah&foo=1

StartServiceCall(url, HttpMethod.GET, postData);
}
}

// Product Add Service.
public class ProductAddService : BaseJsonService<ProductAddResponse>
{
// We have to wrap our request so it is URL encoded properly for MVC.
public class ProductAddWrapper
{
public ProductInfo product { get; set; }
}

public void AddProductAsync(ProductInfo productToAdd)
{
var url = ExampleUrlHelper
.Instance
.GetControllerActionParameterUrl("Product", "Add", string.Empty);

var postData = new ProductAddWrapper()
{
product = productToAdd
}.Postify();

StartServiceCall(url, HttpMethod.POST, postData);
}
}
}


Notice I've copied and pasted the request and response classes from the MVC project. This is a possible down-side to doing services this way. You won't get the autogenerated code that you get from a WCF service, but on the other hand, you will be better prepared in the long run to consume services from other websites that don't expose WCF implementations.


What we are doing is just preparing a URL and then making a request. The actual parsing of the JSON and converting it to our Result class is done by a DataContractJSONSerializer in the BaseJsonService class. To handle the result, or an error, just subscribe to the relevant events in your service consumer.


The Win Phone 7 App



The problem with the win phone 7 app example code is that everyone has different ways of doing things with WPF. I've put together a little MVVM framework tailored to the Win Phone 7 stuff and have included it with the example source code. I'll skip all the XAML and ViewModel code, because it's pretty standard MVVM stuff. Take a look at this demo video to get a look at how our app looks so far.




Hopefully, you've gotten pretty comfortable using MVC and JSON services with your Win Phone 7 apps. Feel free to use any of the code in this example. The Service4u2 and MVVM4u2 libraries are open source under the Microsoft Public License (Ms-PL).







Now Playing: Counting Crows - Friend of the Devil

Win Phone 7 "Words" Game - Mo Words


My wife and I have been playing a lot of word games lately on our IPhones. I've also been playing around with the Win Phone 7 SDK and I've been looking for a good project to work with. So, as a result, I made a little "Words" game called Mo Words.


I've just recently got it to a point where I could play a whole game. But there is still some work to be done for the play notifications (I'm hoping to get Push notifications working this weekend).


The game uses an MVC 2 website returning JSON responses as it's service layer. I hope to put together a couple posts on how I make data driven win phone apps with MVC 2 websites, including how to authenticate to an MVC 2 site and all that.


So, without further ado, here is a demo video (sorry it's choppy, the loading animations and dragging don't match the smoothness of the actual game, it's much better in person) and some screen shots.












Now Playing: Animal Collective - My Girls

Monday, July 12, 2010

FatSecret Sharp - C# Nutrition and Exercise Tracking Services


I started looking into FatSecret.com's REST API this weekend after wondering how hard it would be to make a Food Tracking App for Win Phone 7.


My first step was to take a look at their REST API Documentation, which shows a list of their available methods and how to authenticate using OAuth. It turns out, the hardest part of being able to get data from their services is the OAuth stuff.


OAuth Primer



Basically, OAuth works like this; You get a Consumer Key and a Consumer Secret from their API. You use these to "Sign" your requests. The "Signature" is built up using 3 components joined by an "&"; The method you are using to request (POST or GET), the uri of the service (Url Encoded), and the query parameters (ordered alphabetically by key, then value, then Url Encoded).



{HTTPMethod}&{ServiceUrl}&{OrderedParameters}

GET&http://platform.fatsecret.com/rest/server.api&a=foo&oauth_consumer_key=demo&oauth_nonce=abc&oauth_signature_method=HMAC-SHA1&oauth_timestamp=12345678&oauth_version=1.0&z=bar


Final Version:

GET&http%3A%2F%2Fplatform.fatsecret.com%2Frest%2Fserver.api&a%3Dbar%26%26oauth_consumer_key%3Ddemo%26oauth_nonce%3Dabc%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D12345678%26oauth_version%3D1.0%26z%3Dbar


Then you make your request and hope everything matches up on their side.


FatSecret C# Service Wrappers



The end result of digging into the API was a library to wrap the nutrition and exercise services. Now there is an easy way to search for nutrition information in C#. Visit the FatSecretSharp project on codeplex for examples and code. I'm hoping to start making a Win Phone 7 Application for Food Tracking in the next couple weeks.



Now Playing: Weird Al - Fat