Wednesday 23 March 2011

Using the SharePoint 2010 Silverlight Client Object Model to Update Documents

Cross-posted from Jason Lee's Blog

Earlier this month, I blogged on how you can use the Silverlight client object model to retrieve files from a SharePoint document library. This time, let's take a look at how you can add or update files in a document library from Silverlight.

Just like the process for retrieving files, the process for adding or updating files differs between managed .NET clients and Silverlight clients. The Silverlight client object model does not support the File.SaveBinaryDirect method, so the recommended approach for managed clients is not available to us. From a Silverlight client, the high-level process is as follows:

  • Convert the contents for your new file to a byte array
  • Create a FileCreationInformation instance to represent the new file
  • Add the file to a folder in a document library

The code should resemble the following:

ClientContext context = ClientContext.Current;
String fileContents = "This is the contents of my file";
String fileUrl = String.Format(@"{0}/{1}/{2}/{3}",
   new String[]
      {context.Url, libraryPath, folderName, filename});

//Convert the file contents to a byte array
System.Text.UTF8Encoding encoding =
   new System.Text.UTF8Encoding();
Byte[] fileBytes = encoding.GetBytes(fileContents);

//Create an object to represent the file
FileCreationInformation fileCreationInfo =
   new FileCreationInformation();
fileCreationInfo.Url = fileUrl;
fileCreationInfo.Content = fileBytes;
//Overwrite the file if it exists, create if it doesn't
fileCreationInfo.Overwrite = true;

//Add the file to a library
List targetList =
   context.Web.Lists.GetByTitle("My Document Library");
targetList.RootFolder.Files.Add(fileCreationInfo);
targetList.Update();
context.ExecuteQueryAsync(SaveFileSucceeded,
   SaveFileFailed);

And that's how you save a file to a SharePoint document library. You don't need to do anything specific in the callback methods, other than check for errors or report success back to the user. Note that you don't need to add your file to a specific folder in the document library—you can simply add it to the root folder, and SharePoint will use the URL you provided to put it in the right place. Unlike the server-side object model, the Silverlight client object model doesn't expose a collection of files on the Web object.

One limitation of this approach is that it doesn't allow you to specify a content type or provide any metadata for the file. I plan to look a little deeper into this in a later post.

Monday 21 March 2011

HTML5: Quick Start–Page Template

Interestingly the minimum markup required for an HTML5 page to be a valid HTML5 page is extremely minimal:

<!DOCTYPE html>
<meta charset=utf-8>
<title>Valid HTML5</title>

That’s it. No <head> tag, no <body> tag, or even an <html> tag is required in order to be a valid HTML5 page. Seriously! Head on over to http://html5.validator.nu/ and enter the code above, and then see for yourself.

You might ask yourself—as I certainly did—why would that be? Why would HTML5 be so lax? The answer is that these three elements are completely, entirely and absolutely optional.

The simple reason that these, apparently essential, elements are optional is because browsers assume them anyway—they are so important that browsers don’t trust you to add them in the first place. Below is an image of what the new shiny IE9 browser renders assuming a document with the exact same markup as shown above:

image

Does that mean that we should not add these elements to our production HTML5 documents? Absolutely not! While the above markup is the minimal legal and valid HTML5 markup, is it far from the minimal, most maintainable and practical HTML5 markup. What follows is my opinion of the latter:

<!DOCTYPE html>
<html lang=en>
<head>
  <meta charset=utf-8>
  <title>##PAGE TITLE##</title>
</head>
<body>
  <p>##Content##</p>
</body>
</html>

The above is actually the contents of my very own template.htm file, which I use as the basis for all my HTML5 markup. Note the use of the lang attribute, to help screen readers get the language right—another reason to ensure that you have an <html> element.

Also note that I’m not using quotes for my attribute values; there is nothing deep and meaningful here. I omit them not because I have been oppressed by the dogma of XML for so many years that now I’m rebelling in my own small way, running riot removing quotes left-right-and-centre; removing quotes because I can—OK, well maybe it is that, but it’s not like I’m running with scissors or anything. Use quotes, don’t use quotes; really, it doesn’t matter—all that really matters is that you’re consistent with whichever approach you ultimately take.

As usual, if you have any comments, questions, flames, or enhancements I would love to hear from you. In the meantime, think deeply and enjoy.

-PJ

Thursday 17 March 2011

Using the SharePoint 2010 Silverlight Client Object Model to Retrieve Documents

Cross-posted from Jason Lee's Blog

This week I've been working on migrating a Silverlight application to SharePoint 2010. The application in question uses some fairly complex XML files as a data source, and currently relies on a custom Web service to retrieve and update these files. We want to modify the application to retrieve the XML files from a SharePoint 2010 document library. MSDN provides a good article on how to use the managed .NET client object model for SharePoint 2010 to retrieve and update documents in a SharePoint document library. However, this scenario becomes a little more challenging from a Silverlight client, as some of the required classes are unavailable in the Silverlight version of the client object model.

When you work with the managed client object model, the recommended approach for retrieving the contents of a file is to call the synchronous File.OpenBinaryDirect method. This returns a FileInformation instance that exposes the contents of the file as a stream. However, the FileInformation class is not included in the Silverlight client object model. Instead, the Silverlight client object model includes an alternative, asynchronous version of the File.OpenBinaryDirect method. This returns null, but exposes the contents of the file as a stream through the event arguments in a callback method.

Let's take a look at the code. Suppose we want to retrieve both the metadata for the file and the contents of the file.

ClientContext context = ClientContext.Current;
List targetList =
context.Web.Lists.GetByTitle("My Document Library");
CamlQuery query = new CamlQuery();
query.ViewXml =
   @"<View Scope='RecursiveAll'>
      <Query>
         <Where>
            <Eq>
               <FieldRef Name='FileLeafRef' />
               <Value Type='Text'>input.xml</Value>
            </Eq>
         </Where>
      </Query>
   </View>";

ListItemCollection targetListItems = targetList.GetItems(query);
context.Load(targetListItems);
context.ExecuteQuery();

We can now retrieve document metadata from the list item. For example, we could use the following code to establish when the document was created.

if(targetListItems.Count == 1)
{
   ListItem item = targetListItems[0];
   DateTime createdDate =
      Convert.ToDateTime(item["Created_x0020_Date"]);
}

To get the contents of the file, we use the Microsoft.SharePoint.Client.File.OpenBinaryDirect method and specify callback methods:

String serverRelativeUrl =
   @"/sitename/libraryname/foldername/input.xml";
File.OpenBinaryDirect(context, serverRelativeUrl,
   OnOpenSucceeded, OnOpenFailed);

In the callback method, we can read the contents of the file from the stream and do something useful with it.


private void OnOpenSucceeded(object sender, OpenBinarySucceededEventArgs args)
{
   StreamReader strReader = new StreamReader(args.Stream);
   String fileContents = strReader.ReadToEnd();
   strReader.Close();

   //Do something with the file contents
}

In a nutshell, that's how you retrieve SharePoint 2010 documents from a Silverlight client. Note that I used the synchronous ExecuteQuery method, rather than the asynchronous ExecuteQueryAsync method, to send my queries to the server. Silverlight will not allow you to block the UI thread, so if you want to use this approach you need to run your code on a background thread (for example, by using ThreadPool.QueueUserWorkItem to invoke your logic). You might find this approach preferable if you need to send multiple queries to the server—otherwise you can end up with a tangled web of nested callback methods.

Next time, I'll take a look at creating, updating, and deleting documents from a Silverlight client.

Wednesday 9 March 2011

Using Sequences in SQL Server "Denali"

Over the years, SQL Server developers have become more and more inventive at generating sequential ranges of numbers. The identity column works fine for a single table or view, however when you want a similar effect across multiple tables, issues abound. Hence, a collective sigh of relief was heard with the introduction of the SEQUENCE keyword in SQL Server "Denali". It's also useful when you want to generate a key value before actually adding the row to a table or to use the same key value for records spread across multiple tables.

So let's start by looking at the simplest use of sequences. In the following example, I create a sequence and use it to assign customer numbers in an online shopping application.

USE MyShop;
GO

CREATE SEQUENCE Shopping.OrderNumberSequence
INCREMENT BY 10;
GO

When you create a sequence, you can specify the start value, the increment, and the minimum and maximum values. The increment can be a positive value for increasing sequences or a negative value for decreasing sequences. The minimum and maximum values define the start and end points of the sequence, with the default settings being the minimum and maximum values for the data type of the sequence.

You can use the sequence as a default value for columns in your table by using the NEXT VALUE statement. Here, I'll create a table and specify to use the sequence to generate order numbers.

CREATE TABLE [Shopping].[Orders](
[OrderNumber] int PRIMARY KEY DEFAULT (NEXT VALUE FOR Shopping.OrderNumberSequence)
[CustomerNumber] int NOT NULL,
[OrderDate] date NOT NULL,
[OrderStatus] int NOT NULL,
[TotalCost] money NOT NULL)
ON PRIMARY;
GO

When I run this code and then insert a row into the table, the OrderNumber created is -214783648 which is the minimum value for an int. It's not exactly what I'd envisaged though, so I can use ALTER SEQUENCE ... RESTART WITH to reset the initial value for the sequence.

ALTER SEQUENCE Shopping.OrderNumberSequence
RESTART WITH 10;
GO

Altering the sequence has no effect on the existing values used from the sequence, it just reinitializes the sequence to begin at 10. If I'd planned ahead though, I could have simply used the START WITH argument when creating the sequence.

Another key property of a sequence is cycling. You can configure the sequence to restart at the minimum value if the maximum value is reached. Obviously, this removes uniqueness from the sequence, however you can control uniqueness in a table by assigning a trigger to the column using the sequence.

So, what's actually happening to create these values and where are they being stored? If you query sys.sequences, you'll see all the information about the sequences in your database. This catalog view shows you definition of the sequence as well as the current value and some caching information. When you create the sequence, you can define whether to cache values and how many items to cache. If enabled, caching can increase the performance of your applications by decreasing the file access operations they use.

If you create a sequence and define a cache size of 20, when the first value is requested SQL Server will put values for items 1 through 20 into memory and the last value cached is written as the current value on disk. This means that no more disk operations are needed until the 21st value is requested. The trade off of this performance improvement is the risk that should your SQL Server stop unexpectedly, when it restarts it will allocate again from the current value stored on disk, which could result in a gap in the sequence. If that's not a concern to you, consider caching your sequence values. If you need to avoid gaps in the sequence, use the NO CACHE option, but be aware that if you request a number and then do not use it or do not commit the transaction that used it, gaps can still occur.

Finally, to remove a sequence from a database, you use the DROP SEQUENCE statement. As soon as a value from a sequence is used, it loses any links to the sequence, so dropping the sequence has no effect on the tables that used it. However, if you are referencing it from a table definition as I did for the OrderNumber column, you won't be able to drop it until the dependency is removed.

Tuesday 1 March 2011

HTML5: Are we there yet?

If you are a UX/UI/RIA/Interaction developer today, then HTML5 is an important technology for you, whether you develop directly for the Web or not. It is also important to realise that even though the HTML5 spec is still being drawn up—it’s not scheduled for completion until July 2014—much good work has already been done. The fact of the matter is that many elements of HTML5 are available in many modern browsers today—having said that though, even for browsers that do not support your desired HTML5 element or feature natively, there will typically be an alternative for you to degrade to. And as if more convincing were required about the relevance and validity of HTML5 today: it even has a logo!

HTML5 is the Semantic Web and Application Development specification. By that I mean that I think that these are the two most important areas covered by the specification.

The words Semantic Web have been bandied around for years, with various differing opinions on what that actually means. However, the bottom line is that to you it should mean absolutely nothing… well, to you as a consumer of the content—which is absolutely the way it should be. You don’t care that the content has been written, and therefore rendered by your browser, semantically; in fact, your browser probably doesn’t care that much either! But if that is the case, then what’s the point, why should we care about semantic markup at all? The answer is software. To your software, and the software of others, the semantics mean everything.

Consider the following markup for a fictitious blogging site, with classic HTML markup on the left, and semantic HTML5 markup on the right:

Semantic

Even if you know little or nothing about HTML markup, you should be able to hazard a guess as to what the markup in both of these snippets is attempting to describe. In fact, the differences between the two may not be that obvious to you. But consider this: note the class names in the snippet on the left; it is possible to give a tag, a DIV tag in this example, any class name you like, such as header or navigation. So if you’re writing a piece of software to find all the navigation links in a page, what should your code look for? Any DIV tag with a class name navigation? Well, that might work in this case, but what if your software needs to work outside of this scenario, on lots of different pages, out there in the big, bad, World Wide Web, where the markup author has called that class nav or links or site-links or … ad infinitum.

Simply, the markup on the left is ambiguous. The authors intent is not truly captured—merely implied—and software hates ambiguity, in fact, ambiguity breaks software. Now take a fresh look at the semantic version on the right. Is there any ambiguity in where the author intended the navigation links to reside, or even that there are actually navigation links on the page at all? Or the header, or the footer for that matter? No. And that’s what the Semantic Web will give to us, the clear intent of author expressed right there in the markup.

To a XAML-jockey like me this totally resonates and I’m pleased to see this coming to the Web; I think that this is a big deal.


HTML5 Q n A

Should I consider HTML5 for my next Web based project?

Absolutely!

Should I bet the farm on HTML5?

Absolutely!

Should I use HTML5 exclusively for my application development (pah! to Silverlight and Flash)?

Absolutely not! I know I’ve not discussed the application development side of the specification yet, so this question might seem a little out of context—see below—but this is a common question I’ve seen on the Web, and I want to cover here and now. Silverlight and Flash are still extremely powerful, appropriate and relevant technologies available in your toolbox today; you most definitely should be leaning on these as you plan and build your applications, now and probably a long way into the future. I think it extremely unlikely that HTML5 will ever make technologies like these redundant.


Where are we?

As I said above, I’ve not gone into any detail on the second aspect of the HTML5 specification that I think is really important: Application Development. On that front, I’m on a voyage of discovery myself to a large extent, especially with the newer features, so as I navigate this important aspect of the specification—and brush up on my JavaScript along the way—I plan post my thoughts and findings as I go.

The next post will be about the minimum markup required to be a valid HTML5 page, along with my typical HTML5 page template, followed probably by a post on the much talked about Canvas element. As usual, if you have any comments, questions, flames, enhancements I would love to hear from you. In the meantime, think deeply and enjoy.

-PJ