Thursday, November 24, 2011

WinRT File Access

In my last post I showed how to use an OpenFilePicker in a WinRT application to get access to a file selected by the user. Now let’s take a look at how you access the file system directly without prompting the user. We will start with a simple application that lists the names of the files in the user’s Picture Library.
Start by creating a C# Windows Metro Style Application. Within the Grid element add the following XAML to create textblock we can use to display the name.

<TextBlock x:Name="TextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top"/>

In the code behind add the following code to handle the UserControl_Loaded event:

private async void UserControl_Loaded(object sender, RoutedEventArgs e)
{

var folder = KnownFolders.PicturesLibrary;
var files = await folder.GetFilesAsync();

foreach (StorageFile file in files)
{ 
    TextBlock.Text += file.FileName + ":" + file.ContentType + "\n"; 
}

}

Before running the code, select Exceptions from the Debug menu and check Common Language Runtime Exceptions Thrown. Now run the application and you will notice that it throws a System.UnauthorizedAccessException. Why does this happen?

As I mentioned in my last post, WinRT apps run in a pretty strict sandbox and by default have very limited access to the file system. We got around this last time because we let the user pick a file, so they would have full knowledge of what they are allowing the application to access. But in this case, since we are directly accessing the file system, we get an exception. To solve this problem, double click Package.appxmamnifest in the solution explorer the click on the Capabilities tab.

clip_image002

On this screen we can specify what we want application to be allowed to do. To give the application access to the Picture Library, put a check next to Picture Library Access. If you then re-run the application you will not get an exception and a list of the pictures will be displayed. At first this might seem a little pointless. If the programmer can just click a check box to get access it’s not particularly good security. The value is that it will make it much easier for the prospective user of the app to know what the app is allowed to do. Although we haven’t seem Microsoft’s Windows 8 app store yet, it’s entirely possible that when we look at the information about an app before we purchase it, we will able to see a list of these Capabilities so we know exactly what the app has access to.

Now that we understand about Capabilities, lets look at how the code actually works. In the first line we create a new folder object from one of the KnownFolders. In this case the code selects the PictureLibrary, but we could also select folders like the MusicLibrary, VideosLibrary, or DocumentLibrary.

Once we have the folder object the second line calls it’s GetFilesAsync method to return a list of StorageFile objects for the files in the folder. As always with WinRT, if a method could potentially take more the 50ms to run, it’s executed asynchronously. The next three lines iterate through the list of StorageFiles and display their names.

Friday, October 21, 2011

Windows 8 Metro File Picker

This is one of a series of posts I have been doing while exploring the new WinRT environment in Windows 8. In this article I am going to talk about the file pickers functionality.
In .NET apps when we need to prompt the user to select a file we have a common dialog that can be displayed. WinRT Metro apps provide something similar called a picker. The way the file picker works is particularly import for WinRT applications. These applications run in a sandbox and by default they have limited access the user’s files. If the app needs to have arbitrary access to user files it must declare this in the Capabilities section of its manifest. This, in theory, would allow the user to know exactly what the app is allowed to do before they download it.
This is where the file picker comes into play. The file picker returns a StorageFile object which can be used to directly access only the file that the user picked. Since the user is in complete control of the selection there is no need to declare this capability in the manifest.
To demonstrate a file picker let’s create a small application that will allow the user to pick an image file and then display that file in an image control.
First create a new C# Windows Metro Style Application. In the XAML view of MainPage.xaml, add the following code inside the Grid element:

<Button x:Name="UIOpenFile" Content="Open File" HorizontalAlignment="Left" Margin="17,18,0,0" VerticalAlignment="Top" Click="UIOpenFile_Click"/>

<Image x:Name="UIImage" HorizontalAlignment="Left" Margin="27,74,0,0" VerticalAlignment="Top" />

In the code behind for MainPage add the following namespaces:

using Windows.Storage.Pickers;
using Windows.UI.Xaml.Media.Imaging;

Then add the following code:

async private void UIOpenFile_Click(object sender, RoutedEventArgs e)
{
    var picker = new FileOpenPicker();
 
    picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    picker.ViewMode = PickerViewMode.Thumbnail;
    picker.FileTypeFilter.Add(".jpg");
    picker.FileTypeFilter.Add(".jpeg");


    var file = await picker.PickSingleFileAsync();
    if (file == null) return;

    var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
    BitmapImage image = new BitmapImage();
    image.SetSource(stream);
    UIImage.Source = image;
}

When you run the application and click the button you will get a file picker screen open to your picture library. If you pick an image file it will be displayed in the image control. Let look at how this code works.

First note that the event handler is marked as async. Any potentially long running functions in WinRT will run asynchronously so this keyword is needed for this to work.

The first thing we do in the function is create a FileOpenPicker object and set its properties.

The SuggestedStartLocation property specifies one of a series of standard locations that the picker should start in. In this case we are starting in the PictureLibrary, but the user is free to browse to other locations.

The next property, ViewMode, determines how the picker will display the files. There are currently two options:

PickerViewMode.Thumbnail

clip_image002

PickerViewMode.List

clip_image004

The last property we need to setup is the FileTypeFilter. This is a generic list of strings, each being one of the file type extensions that you want to the picker to look for. In this case we are just adding two, .jpeg, and .jpg. Note that if you don’t add any file types you will get an exception when you display the picker, and you can’t use wildcards. I am assuming that Microsoft will eventually need to add a way to pick any file type.

Once the properties are set on the picker we call it’s PickSingleFileAsync() method to display the picker and allow the user to select a single file. The await keyword will cause the function to pause until the picker is closed, but not block the UI thread. The function will return either a StorageFile object or a null if the user canceled the picker.

As I mentioned at the beginning of the article, we don’t get just a filename back from the picker, but a StorageFile object. In the last four lines of the code we use the object to create a read only stream, create a BitmapImage object from the stream, and then finally set that image as the source of the image control.

Wednesday, September 28, 2011

Windows 8 Secondary Tiles

In the past couple posts I have showed various ways of manipulating the start menu tile for an application. Besides manipulating the main tile your app can also create secondary tiles when the user wants to see more information then can easily be displayed on a single tile. You can see an example of this in the Weather app. Open the app and add a second city, right click to bring up the app bar and click Pin City. Once you do this a second tile will appear on the start screen with the information for that city. Let’s look at how you create a secondary tile.
Before you can create a secondary tile you need, at a minimum, a 150x150 pixel image for the tile. Create the image and save it as a .PNG file in your applications Images directory then add it to the application in solution explorer. Set the Build Action property on the image to Content, and the Copy to Output Directory property to “Copy if Newer” or “Copy Always”. Once you have the image you can use the following code to display it:
Note: You will want to include the Windows.UI.StartScreen namespace in your file.

async public void ShowSecondayTile() 
{
  Uri logo = new Uri("ms-resource:images/SecondayLogo.png");
  SecondaryTile secondaryTile = new SecondaryTile("MySecondaryTile1",
    "Secondary Tile",
    "Hello World Secondary",
    "Tile 1 activated",
    TileDisplayAttributes.ShowName,
    logo);
  bool isPinned = await secondaryTile.RequestCreateAsync();
}

First we need to create a Uri object to point to the tile image we added to the images folder. Next we create the secondary tile object. The parameters passed to the constructor mostly correspond to the properties you set in the manifest for the default startup tile.

  • - tileId: Since you can create more the one secondary tile the tileId uniquely identifies the tile to your application. If you add more then one tile with the tileId the later one will replace the earlier.


  • - shortName: A name that is displayed on the tile if you set the ShowName attribute.


  • - displayName: The name displayed when you hover over the tile.


  • - arguments: A string that you want passed back to your application when the tile is clicked. We will talk more about this later.


  • - displayAttributes: Any attributes you need to set on the tile, for example ShowName.


  • - logoRefernce: Uri of the image to use for the square tile.

Besides the properties you set in the constructor there are also properties on the object for setting things like the WideLogo, SmallLogo, ForegroundText, etc.

Once you have the SecondaryTile object setup the last line requests the creation of the tile. When that line is executed the user will see a popup that looks like this:

clip_image001

This shows an image of the tile, gives the user a chance to change the shortName and has a button to accept the request. If the user accepts, the function will return a true. If they click off the popup the request will be denied and the function will return a false.

One interesting thing to note in this line is the “await” keyword. Await, along with async in the function declaration are new keywords in C# that are used to handle asynchronous functions and you will see these used a lot in Windows 8 Metro applications. The details of how these work are beyond the scope of this article, but in short, execution will not continue to the next line until RequestCreateAsync is complete, but unlike in synchronous programming it won’t block the UI thread either. Essentially the ShowSecondayTile function is suspended until the async function completes.

Once the secondary tile is displayed the user can remove it from the start menu by right clicking it and selecting Remove from the app bar. We can also have our application request the removal of a secondary tile with this code:

async private void RemoveSecondaryTile() 
{
    var secondaryTile = new SecondaryTile(“MySecondaryTile1”);
    bool isDeleted = await secondaryTile.RequestDeleteAsync();
}

The first line creates a SecondaryTile object based on the tileId we set when we created the tile, and the second line requests the removal. The removal works just like the creation where the user will be prompted if they want to remove it and the functional will return true of false based on what the user chooses to do.

When the user clicks on a secondary tile, Windows will launch your application just as if they had clicked on the main tile. To determine which secondary tile launched the app you can use the Arguments property on SecondaryTile object. In your application’s App.xaml.cs file you will see the following default code:

protected override void OnLaunched(LaunchActivatedEventArgs args) 
{
    Window.Current.Content = new MainPage();
    Window.Current.Activate();
}

The LaunchActivatedEventArgs object contains a string property called Arguments that will contain the contents of the Arguments property we set on the secondary tile. One way to handle this would be to modify the MainPage contructor to accept a LaunchActivatedEventArgs object as a parameter and then modify the OnLaunched event to pass args to MainPage. In the MainPage constructor you can then get the Arguments property and handle it as needed.

While digging a little deeper into secondary tiles I noticed that both the TileUpdateManager and BadgeUpdateManager have methods to create updaters for secondary tile. For badges you call use a line like this to get a secondary tile updater:

var tileUpdater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(“MySecondaryTile1”)

where the parameter passed is the tileId of the secondary tile. This updater would then allow us to show badges on the tile. We should be able to do something similar for notifications but I always got an exception when I called CreateTileUpdaterForSecondayTile(“MySecondaryTile1”) . Not sure if I am doing something wrong or if this is a bug.

Monday, September 26, 2011

Windows 8 Metro Tile Badges

In my last post I showed how to make notifications appear on an application’s start menu tile. In this post I will show another way to show information on the tile, badges. Badges are small icons that show up in the lower right corner of a tile on top of either the default startup tile, or on top of a notification. The process for displaying a badge is pretty much the same as displaying a notification, it just uses difference classes.

var xmlDocument = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);
xmlData.Text = xmlDocument.GetXml();
var textNode = xmlDocument.SelectSingleNode("/badge");
textNode.Attributes[0].NodeValue = UIBadgeValue.Text;
var badge = new BadgeNotification(xmlDocument);
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(badge);


The first line gets the XML template for the badge. There are two template types for badges, Number and Glyph. Number display a one or two digit number. For example you could use this to display the number of unread e-mails in a e-mail application. The number badge looks like this:

NumberBadge

The second type is Glyph which displays one of a series of predefined icons. A error glyph badge looks like this:

GlyphBadge

The schema for both types of badges is the same:

<badge value=””/>  

The next two lines set the value attribute in the schema. For the number badge this will be one or two digits. For the glyph badge it will be one of the following values: none,activity,alert,available,away,busy,newMessage,paused,playing,unavailable,error The last two lines create a badge object and display it on the tile. Removing a badge works just like removing a notification:

BadgeUpdateManager.CreateBadgeUpdaterForApplication().Clear();

Just like notifications, badges have a ExpirationTime property that should control when the badge expires, but I have not had any luck getting that property to work.

Thursday, September 22, 2011

Metro App Tile Notification


In my last post I showed you how to configure the start menu tile for a Windows 8 Metro app. The tiles can be used for more the just displaying a static startup icon, they can also display content that is relevant to your app so that the user can get information from the app without even leaving the start menu.
There are a couple ways to do this. The first one I will show is notifications. A notification displays some content on the tile instead of its default text and icon. A good example of this is the Stocks app that comes with Windows 8. When you start the app the current stock information will be setup as notifications so when you go back to the start menu you will see the tile rotate through the values for each stock market. Let's take a look at how you do a notification in a C# Metro app.
Note: The current version of Windows 8 is pre-beta and still a little buggy. I have found this especially true with the notifications, sometime they just don't work for no apparent reason.

The appearance of a notification is controlled by an XML template, so the first step in sending a notification is to get a template to work with like this:

Note: You will want to include the Windows.UI.Notifications namespace.

var xmlTemplate = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideText01);

This command will return an XmlDocument object containing the TileWideText01 template that you can fill out with the data you want to display. You can see a full list of all the templates here. Unfortunately that page doesn't show the actual XML in the template which you need to know before you can modify it. You may want to put a TextArea on your application form and set it's Text property to xmlTemplate.GetXml() to see the XML. The XML for the TileWideText01 template looks like this:

<?xml version="1.0" encoding="utf-16"?> 

<tile>
  <visual lang="en-US">
    <binding template="TileWideText01">
      <text id="1"></text>
      <text id="2"></text>
      <text id="3"></text>
      <text id="4"></text>
      <text id="5"></text>
    </binding>
  </visual>
</tile> 

and the resulting 

tile will look something like this:

clip_image002

To get our text into the notification we need to modify the XML. Here I use XPath to select the first text node and set its value:

var textNode = xmlTemplate.SelectSingleNode("/tile/visual/binding/text[@id='1']"); 
var newText = xmlTemplate.CreateTextNode(text); 
textNode.AppendChild(newText); 

Next we need to create a tileNotification object from the xml:

var tileNotification = new TileNotification(xmlTemplate); 

Finally we need to update the notification on the tile:

var tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication(); 
tileUpdater.Update(tileNotification); 

If you put this code in the form constructor of a C# Metro app, run the app, and then switch to the Start screen you will momentarily see the default startup tile, then the notification will slide into view. The notification will continue to be displayed even if the application is terminated, the computer restarted, or even if the app is un-installed and re-installed (I think this is un-intended and may change in later versions.)

There are two ways for you to remove the notification. The first way is to replace it with a different notification. The second way it to clear it with the following command:

TileUpdateManager.CreateTileUpdaterForApplication().Clear(); 

This will remove the notification and restore the tile to the initial startup appearance.

Normally you can only have one notification active at a time, but there is also a way to show multiple notifications. First execute this command:

TileUpdateManager.CreateTileUpdaterForApplication()

.EnableNotificationQueue(true); 

Then add up to five notifications and the tile will rotate between them. If you add more than five the most recent five added will be shown.

One other thing you can do with notifications is set an expiration date and time. You do that like this:

tileNotification.ExpirationTime = new DateTimeOffset(DateTime.Now.AddMinutes(5)); 

This command will make a notification expire 5 minutes after it has been added to the tile. After the notification expires the initial startup tile will be displayed just like when you use the Clear command.

Sunday, September 18, 2011

Metro App Tile Basics

In my last post I showed the basics of how to create a simple Metro app. By default the tile displayed on the start screen for the app is not very useful, so I'll show you how to change it.

First open the app you created last time, or create a new blank Metro app. When the project is open double click on Package.appxmanifest in the Solution Explorer, this will bring up an editor screen for the manifest. On the Application UI tab scroll down a little bit to the Tile section:

clip_image002

The first two properties define the image that will be used for the small and large tiles on the start screen. These images can either be .png or .jpg. The small logo must be 150x150 pixels, and the large must be 310x150 pixels. If you don't specify a large logo, then you will not be given the option to switch to a larger tile on the start screen.

The next property, Small Logo, is used to specify the logo that will appear for the application on the search results screen. This must be a 30x30 pixel .png or .jpg.

The Show Name property determines if the name of the application should be displayed on the tile. If you do not specify a Short Name the Display Name will be used. You can also control the color of the name text by using the Foreground Text drop down. Here is an example of a large logo with a solid blue background and the name shown:

clip_image003

The Background Color property is used to control the background color of the tile and the splash screen. You will only see the background color on a tile when you leave parts of the image transparent.

Friday, September 16, 2011

Windows 8 Metro Apps

One of the major new features in Windows 8 is the concept of Metro style apps. The term “Metro” is used to describe a new design style for application user interfaces and an apps overall user experience. The Metro style interface can currently be seen in the Microsoft Zune media player and the Windows Phone 7 operating system. For more information on Metro check out Microsoft’s Metro Design Language page.
Metro apps in Wind0ws 8 run under a totally new operating environment called Windows Runtime or WinRT. I am not going to get into the details of WinRT here since quite honestly I have still not entirely gotten my head wrapped around it. Fortunately WinRT supports various languages and technologies that you are probably already familiar with so it’s not to hard to  get up to speed writing Metro apps.
If you have installed the Windows 8 Developer Preview with developer tools you can use this walkthrough to make your first Metro app.

  1. Startup Visual Studio 11 Express
  2. Click New Project.
clip_image002
You will see templates for a Windows Metro style apps for each of the supported languages. Note that this preview version of Visual Studio is only setup to do Metro apps. Javascript apps use HTML and CSS for their user interface, but unlike browser based apps they can have full access to the WinRT runtime. VB.NET, C#, and Visual C++ all use XAML for their UI’s which should be familiar to anyone who has done WPF or Silverlight apps.
  1. Select the Windows Metro style template under Visual C#, and then click Application in the center panel. This will create a basic blank Metro app.
  2. For the Name of the application enter HelloWorld then click OK.
If we ran the app now we would just get a blank screen so let’s add a little bit of content.
  1. In the XAML view, between the Grid tags, add the following code:
<TextBlock Text="Hello World" HorizontalAlignment="Center" Margin="20" TextWrapping="Wrap" VerticalAlignment="Top" FontFamily="Georgia" FontSize="16"/>

  1. Save you program then click Run.
Once the program compiles and runs you will get a black screen with a clock icon as the app loads then a black screen with the words “Hello World” in the top center. The first thing you will notice is that the app takes up the entire screen, this is a major design elements of Metro apps. If you have a large enough screen Windows 8 will provide the ability to do two apps side by side, but the standard is going to be one app displaying at a time.


Another thing you will notice is that there is no obvious way to close the app. The app lifecycle is much different in Metro. When you switch from one app to another the current app goes into a suspended state but remains in memory, then if you switch back to it, it will become active again. If memory starts running low the OS will automatically start terminating suspended apps.


Press the Windows key to bring up the Metro Start screen, scroll all the way to the right and you will see this icon:


clip_image001


This is the default icon that represents you new app. If you hover your mouse over it the Hello World name will pop up. To get back to Visual Studio just click the Desktop tile on the Metro start screen. Since your app is still suspended in the background remember to click stop to terminate it.

Thursday, September 15, 2011

New Development Tools

In conjunction with Microsoft’s Build conference this week they have released preview versions of quite a few development tools.

Windows 8 – As I mentioned yesterday the developer previews of Windows 8 have been released.

ASP.NET MVC 4 Developer Preview 

Visual Studio 11 Developer Preview 

.NET Framework 4.5 Developer Preview

ASP.NET  4.5 Developer Preview

WCF Web API Preview 5

Windows Azure Toolkit for Windows 8

So many new technologies to learn, so little time!

Wednesday, September 14, 2011

Windows 8

Yesterday at Microsoft’s Build Conference they provided a lot of new information for developers about Windows 8. I highly recommend checking out the day one keynote speech, it’s long but worthwhile.

If you want to try out Windows 8 you can download a developer (pre-beta) preview here. There are 64 and 32 bit versions of just the OS, as well as a 64-bit version that also contains early versions of Visual Studio 11 and Expression Blend 5 that will allow you to immediately get started with Windows 8 development.

To try it out I decided to load the 64-bit version with the tools in a virtual machine. I first tried if with VMware Workstation, but it seemed to have a problem with the Win 8 installer and it failed before the install even got started. Virtual PC doesn’t support 64-bit, guests but I presume the 32-bit version of Windows 8 will work with it. I finally got it installed using Oracle Virtual Box, just remember that you need to have a processor that supports hardware virtualization to do this. The install went very smoothly with the exception of one crash while entering my Windows Live password. After a re-start the install process finished without any more problems.

The new Metro user interface can be a little tricky at first, especially if you don't have a computer with touch capability, so here are a few tips to help you out.

  1. Be sure you have you screen resolution set to at least 1024x768 or the Metro style apps will not start up.
  2. You can click on the Desktop tile to get to a Windows 7 style desktop. Once you have done that you can switch back and forth between the desktop and the Metro start screen using the Windows key.
  3. There is no Windows 7 style start menu; it's just the Metro start screen. There doesn't seem to be a way to turn the old start menu back on and no indication if Microsoft will add this feature or not.
  4. If you don't have touch, then you will need to fall back to keystrokes for a lot of things. Here are a couple useful ones:

Windows Key+F: Opens the search files panel

Windows Key+Q: Opens the search apps panel

Windows Key+C: Opens the charms panel

Windows Key+I: Opens settings charm

  1. To shut down Windows (you would think this would be obvious), press Windows Key+I, click the Power icon, then click Shut down or Restart from the popup menu.

Sunday, September 4, 2011

GridView Header Issue

 
If you have worked with the ASP.NET GridView you may notice an odd problem relating to the header text alignment. If you set the grid’s HeaderStyle.HorizontalAlign property to Left the headers will appear left aligned in Chrome, Firefox and older versions of IE (as well as IE compatibility mode), but in later version of IE the header text will stay centered instead of left aligned. Here is the HTML that comes from the GridView:

<table cellspacing="0" rules="all" border="1" id="GridView1" style="width:50%;border-collapse:collapse;">     
    <tr align="left">                
        <th scope="col">Field1</th>
        <th scope="col">Field2</th>
        <th scope="col">Field3</th>        
    </tr>         
    <tr>               
        <td>Data1</td>
        <td>Data2</td>
        <td>Data3</td>        
    </tr> 
</table>

The reason for this alignment problem is the align attribute on the <tr> element. In the later version of IE this alignment is not inherited by the <th> elements like it is in other browsers. I have been doing some reading on this issue and there seems to be some debate as to whether this is what the HTML specification intended or not. I will leave that debate to others and just show how to resolve the problem.
If you are not auto generating the columns you can fix this by setting the HeaderStyle.HorizontalAlign property to the appropriate value for each of your columns. So in this example I would set them to Left. The GridView will now output the following HTML:

<table cellspacing="0" rules="all" border="1" id="GridView1" style="width:50%;border-collapse:collapse;">
    <tr align="left">                
        <th align="left" scope="col">Field1</th>
        <th align="left" scope="col">Field2</th>
        <th align="left" scope="col">Field3</th>         
    </tr>
    <tr>
        <td>Data1</td>
        <td>Data2</td>
        <td>Data3</td>
    </tr>
</table>


You will see that each <th> element now has an align attribute which will work the same in any browser.


You also can achieve the same thing using CSS which has the advantage of working whether you are auto generating the columns or not. To do this first add this style to either the header of your page, or to a CSS file:


<style type="text/css"> 
    .gvclass table th {text-align:left;} 
</style> 

Then wrap your GridView in a div tag that uses the .gvclass:

<div class="gvclass"> 
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" Width="50%"> 
    </asp:GridView> 
</div>

Sunday, February 27, 2011

Salesforce REST API Query Deserialization


In my last article about the Salesforce REST API I showed how to query for records. The JSON encoded result of the query looks something like this:

{
"totalSize" : 2,
"done" : true,
"records" : [ {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000Q9SFkAAN"
},
"Id" : "0017000000Q9SFkAAN",
"AccountNumber" : "12345",
"Name" : "Big Account"
}, {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000O1LiGAAV"
},
"Id" : "0017000000O1LiGAAV",
"AccountNumber" : "6789",
"Name" : "Small Account"
}]
}


The next question is how to de-serialize this back into an object. Like I have shown before we can use the JavaScriptSerializer class in the .NET Framework to do this, but what would the object model have to look like? One way we could do it is like this:

public class sfdcAttributes
{
    public string Type { get; set; }
    public string Url { get; set; }
}


public class sfdcAccount
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string AccountNumber { get; set; }

    public sfdcAttributes Attributes { get; set; }    
}

public class sfdcAccountCollection
{
    public bool Done { get; set; }
    public int TotalSize { get; set; }
    public string nextRecordsUrl { get; set; }
    public List<sfdcAccount> Records { get; set; }
}


This will work but it has two problems. First we would have to create a collection class for each SFDC object we want to work with and most of the code for that class would be duplicated from one object to the next. The second problem is that because we put the Attributes property in the sfdcAccount class we can’t use it do do inserts or updates since Attributes isn’t a property on the Account object.


To solve the first problem we can use generics:

public class sfdcCollection<T>
{
    public bool Done { get; set; }
    public int TotalSize { get; set; }
    public string nextRecordsUrl { get; set; }
    public List<T> Records { get; set; }
}


This is a generic SFDC collection class that we can use with any type of object. To solve the second problem we need to pull out the Attributes property. Here is a way to handle that:

public class sfdcAccountForCollection : sfdcAccount
{
    public sfdcAttributes Attributes { get; set; }

}


Here we create a class just for use with the collections that are returned by the query function. We inherit from the base sfdcAccount class so it keeps this additional class very simple. To use these classes to de-serialize the JSON response, we just do this:

sfdcCollection<sfdcAccountForCollection> accts = ser.Deserialize<sfdcCollection<sfdcAccountForCollection>>(json);

Thursday, February 24, 2011

log4net Presentation

 

For anyone who attended my presentation on log4net at the PhillyNJ.NET meeting 2/21/2011, here are the related file.

Power Point Presentation

log4net Demo Source Code

If you are in South Jersey of the Philadelphia area be sure to check out the next meting on March 29th where David Isbitski from Microsoft will do a presentation on Real World Windows Phone 7 Development.

Wednesday, February 9, 2011

Salesforce REST API Query

A couple weeks ago we looked at how to read a record from SFDC using the REST API. The read function has limited usefulness since it requires us to know the internal ID of a record to be able to read it, and in most cases you won’t know this ID. A more useful way of reading records is to use the Query function.
Query allows you to execute Salesforce Object Query Language (SOQL) queries to retrieve a set of records.  SOQL is similar to an SQL SELECT statement. I am not going to go into the details of SOQL, but you can learn more about it here.
The code for doing a Query is pretty much the same as the code I presented in the Salesforce REST API Read Record article, the only difference being the URI. The URI will look something like this:

var uri = instanceURL + “/services/data/v20.0/query?q=SELECT id,accountNumber,name from account


You will see that we have added a query string called q that contains the SOQL query. Note that in SOQL you must specify all the fields you want returned. There is no equivalent of ‘SELECT *’ in SOQL.


The response from the query will look something like this:


{
"totalSize" : 2,
"done" : true,
"records" : [ {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000Q9SFkAAN"
},
"Id" : "0017000000Q9SFkAAN",
"AccountNumber" : null,
"Name" : "Big Account"
}, {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000O1LiGAAV"
},
"Id" : "0017000000O1LiGAAV",
"AccountNumber" : "CC978213",
"Name" : "GenePoint"
}]
}


The first things in the response are two fields called totalSize and done. These are important because there is a limit to the number of record a query can return. My experimentation showed the limit to be 2000 records in this case, but that limit my be different in other situations. The totalSize property tells you how many records met the criteria of the query, even if that total is greater then the record limit. If the total is greater then the done property will be false and there will be an additional property called nextRecordsUrl that looks like this:


"nextRecordsUrl" : "/services/data/v20.0/query/01g7000000FBzMHAA1-2000"


To get the next batch of records you would do another HTTP GET using this URL, and then repeat the process until the done property comes back true.


The actual results of the query will be contained in the records array. Each record will contain a series of attributes, one of which is the URL you can use to read the entire record. Following the attributes will be the fields that you requested in the query.

Saturday, January 29, 2011

Salesforce REST API Update and Delete Record

So far we have looked at how to create and read records from Salesforce using the REST API, so the final two basic operations we need are Update and Delete.

Update

The code for doing an update is almost identical to the code for doing an insert with just two small differences.
First we need to specify the ID of the record we want to update in the URI just like we did for a read:

var uri = instanceURL + "/services/data/v20.0/sobjects/Account/0017000000hX4Iz";

Second we will use PATCH for the HTTP method instead of POST. Not that PATCH isn’t a standard HTTP method, but fortunately the .NET WebRequest class allows for arbitrary methods.
Just like with an insert you put the JSON or XML encoded object into the body of the request. You can put all the fields in the body or just the ones you want to update.  If you decide to use XML for the body don’t forget to change the ContentType from JSON to XML:

req.ContentType = "application/xml";

The only other difference with an update is the response. Unlike the other function we have looked at so far, the content of the response will be empty if the update succeeds.


Delete

Delete is probably the simplest operation. We use the same URI as an update, one that contains the id of the record we want to delete, and set the HTTP method to DELETE. Nothing needs to be put in the body of the request for a delete. Just like an update, if the delete is successful the response will be empty.

Sunday, January 16, 2011

Salesforce REST API Read Record

In my last post I showed how to create a new record in Salesforce using the REST API, now lets look at reading a record.
To access a record you need to add the record’s id to the end of the object URI that I showed in the last post. For example to access a specific account record you would use:
http://na1.salesforce.com/services/data/v20.0/sobjects/Account/001D000000INjVe
The id’s aren’t shown directly when you edit a record in SFDC, but you can find the record id in the URL when you are editing a record. You can also get an id from the response when you create a record as we saw last time.
The code to perform the read will look something like this:

public string ReadData()
{
var uri = instanceURL + "/services/data/v20.0/sobjects/Account/0017000000hX4Iz";

var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + accessToken);
req.Headers.Add("X-PrettyPrint:1");
req.ContentType = "application/json";
req.Method = "GET";

WebResponse resp;

try
{
resp = req.GetResponse();
}
catch (WebException ex)
{
resp = ex.Response;
}

var sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}

This is pretty much the same code we used for the insert but it uses an HTTP GET instead of POST,  and there is no body needed for the request. You will also notice a new header, X-PrettyPrint:1. This will make SFDC return the response in a more readable format with appropriate line breaks and indentation. This header can be used in any of the REST API commands.

The response will contain the JSON formatted Account object. Remember, as always, you can add .xml to the end the URI to have the response returned in XML instead of JSON.

By default this command will return all the fields in the record. You can specify only the fields you want to return like this:

http://na1.salesforce.com/services/data/v20.0/sobjects/Account/001D000000INjVe?fields=AccountNumber,Name

We have added a query string called fields to the URI which lists the fields you want to return.

Saturday, January 8, 2011

Salesforce REST API Record Creation

In my last few articles I showed the basics of how to connect to Salesforce using the REST API and how to use some basic functions. Now lets look at how to actually manipulate the data stored in SFDC. We will start by looking at how to insert a new record.
When you are working with tables (called objects in the SFDC nomenclature), the URI will look something like this:
http://na1.salesforce.com/services/data/v20.0/sobjects/Account/

  • http://na1.salesforce.com  is the instance URL that you get during the login process.
  • /services/data/v20.0/ indicates the version of SFDC you will be using.
  • sobjects/ is the resource we will be accessing, in this case the SFDC objects (tables).
  • Account/ is the name of the object we will be creating the new record in.
To insert a new record we will do an HTTP POST to this URI. In the headers we will pass the authorization token, and in the body we will pass the JSON encoded data we want to insert. For example here is a simple piece of JSON that will insert a new Account with the name TestAccount and number 1234567.
{    
"Name" : "TestAccount",
"AccountNumber" : "1234567"
}

Now lets look at the C# code to perform this insert. First, to simplify the creation of our JSON lets create an Account class that we can serialize.

public class sfdcAccount
{
public string Name { get; set; }
public string AccountNumber { get; set; }

}

Next we will setup our URI and the account object

var uri = instanceURL + "/services/data/v20.0/sobjects/Account/";

var acct = new sfdcAccount();
acct.Name = "NewAccount";
acct.AccountNumber = "123456";

and then serialize the account object into JSON.

var ser = new JavaScriptSerializer();
var body = ser.Serialize(acct);

We can now create our HTTP request.

var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + accessToken);
req.ContentType = "application/json";
req.Method = "POST";


Here we create an HttpWebRequest object pointing to the URI we specified earlier. We then set a header that contains the access token we got during the login process, set the content type to JSON and finally specify that this is an HTTP POST request.

Next we need to add the body of the request. This code will convert our JSON to a byte array an attach it to the request.

byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
req.ContentLength = body.Length;
var os = req.GetRequestStream();
os.Write(data, 0, data.Length);
os.Close();

Finally we execute the request and retrieve the result that SFDC sends back.

WebResponse resp;

try
{
resp = req.GetResponse();
}
catch (WebException ex)
{
resp = ex.Response;
}

if (resp == null) return null;
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();

The try/catch around the request is important. When there is an error executing the command SFDC will return a HTTP response code of 400 which will throw an exception. To resolve this problem we catch the exception and retrieve the response object from the exception.

Assuming there are no errors, SFDC will return a JSON response that looks like this

{
"id":"0017000000hX4BIAA0",
"errors":[],
"success":true
}

First we get back the internal id of the record that was created. We can use this later to read, update, or delete this record. We also get back a true/false field indicating the success or failure of the insert and an errors field. I have not yet found a case where these are used since an error will return a different response. For example if we make the AccountNumber greater the 40 characters we will get the following response:

{
"fields":["AccountNumber"],
"message":"Account Number: data value too large: 1234567890123456789012345678901234567890123456789012345678901 (max length=40)",
"errorCode":"STRING_TOO_LONG"
}