Creating a SharePoint Visual Web Part using Visual Studio 2010

Last year we built a business application for order management for Northwind Traders on the Office and SharePoint platform using Visual Studio 2008 and Office & SharePoint 2007. Lately I’ve been writing articles that show how to upgrade it to Office & SharePoint 2010 using Visual Studio 2010. If you missed them:

I also released the migrated sample application here: http://code.msdn.microsoft.com/OBANorthwind

If you look at the VS2010 solution in that sample you’ll see a few extra projects in there that add more functionality to our application. One of those new pieces is a Visual Web Part that shows low inventory from the Northwind database. Northwind’s operations department not only wants to see Order status in SharePoint (which we built into our workflow) but also wants to be able to quickly eyeball any low inventory. Visual Studio 2010 includes many new project and item templates for SharePoint 2010, one being a Visual Web part. If you’re familiar with ASP.NET development then you can easily start building a SharePoint web part using Visual Studio 2010. Let’s see how we can do that.

Creating a Visual Web Part Project in Visual Studio

First thing you need to do is open Visual Studio as an Administrator. You need to do this when you are programming against SharePoint because the debugger & tools need Administrator access to SharePoint. Visual Studio will warn you if you forget.

Next create a new project and select SharePoint 2010 -> Visual Web Part. (Make sure you select Visual Web Part and not Web Part). Name the project LowInventoryWebPart. The SharePoint Customization Wizard opens. Select your SharePoint site, in my case I’ve created a team site called Northwind.

Notice that “Deploy as a farm solution” is the only option. This means that when you design a visual web part it is available to all site collections on the farm as opposed to a sandboxed solution which is only available at the site collection level. The key difference between these two is what processes they run in, farm being the IIS worker process, which dictates which access levels they have. For more information on the differences see Differences Between Sandboxed and Farm Solutions in the MSDN library.

image

Click Finish and the the ASP.NET designer opens and displays a web user control that we can design. But first we need to add a service reference to our data service. If you recall we are exposing our line-of-business data (in this case the Northwind SQL database) over WCF-REST using a data service. As long as we can access this service from our SharePoint instance once we deploy, then we’re good to go.

To add a Service Reference to the data service, select Project -> Add Service Reference. If your data service is in the same solution as in the case of this one, just click Discover to browse the types that the data service exposes. Set the Namespace to NorthwindService and click OK.

Designing the Visual Web Part and Loading Data

I don’t have any super-fancy design skillz here so we’re just going to create a data-bound GridView and then write a LINQ query to get the low inventory items to display. The key takeaway is that this would be the same code to write if we were writing any ASP.NET webpage, you can even use the Ajax controls in the toolbox. In the next section below we’ll take advantage of the SharePoint server model in order to interact with SharePoint lists, but to pull data from our LOB database it’s standard data access stuff.

So from the Data tab in the toolbox, I’m going to drag a GridView onto the form. I’m also going to drop a Label at the bottom of the form to display any errors or messages. I can style these controls how I like and these styles will be displayed the same way in the Web Part in SharePoint.

image

Right-click on the designer to open the code-behind. In the Page_Load event handler we’ll write the code to load the low inventory from our data service:

Imports System
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports LowInventoryWebPart.NorthwindService

Partial Public Class LowInventoryWebPartUserControl
    Inherits UserControl

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
        'Webpart Code to display Low Inventory:
        Try
            Dim ctx As New NorthwindEntities(New Uri("http://myserver/Northwind.svc/"))

            Dim result = From p In ctx.Products _
                         Where p.UnitsInStock <= p.ReorderLevel _
                         Order By p.UnitsInStock

            Me.GridView1.AutoGenerateColumns = True
            Me.GridView1.DataSource = result.ToList()
            Me.GridView1.DataBind()

        Catch ex As Exception
            Me.Label1.Text = ex.ToString
        End Try
    End Sub

End Class

Debugging the Web Part

Let’s test this so far. Set the LowInventoryWebPart project as the startup project of your solution (if it isn’t already) and set a breakpoint on the LINQ query. Hit F5 and Visual Studio will recycle the IIS worker process, package & deploy & activate the feature, and attach the debugger automatically for you. This is shown in the Output window and it’s fun to watch so you may want to pin that window open. :-)

------ Deploy started: Project: LowInventoryWebPart, Configuration: Debug Any CPU ------

Active Deployment Configuration: Default

Run Pre-Deployment Command:

  Skipping deployment step because a pre-deployment command is not specified.

Recycle IIS Application Pool:

  Skipping application pool recycle because no matching package on the server was found.

Retract Solution:

  Skipping package retraction because no matching package on the server was found.

Add Solution:

  Adding solution 'LowInventoryWebPart.wsp'...

  Deploying solution 'LowInventoryWebPart.wsp'...

Activate Features:

  Activating feature 'Feature1' ...

Run Post-Deployment Command:

  Skipping deployment step because a post-deployment command is not specified.

========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

========== Deploy: 1 succeeded, 0 failed, 0 skipped ==========

The nice thing is that Visual Studio handles all the deployment as well as all the cleanup. When you close the debugger the feature is deactivated and the package is retracted and deleted. Notice that you can also specify pre and post deployment commands, plus a whole lot more. The Feature and Package designers are very flexible. (For more information watch this Channel 9 Interview: SharePoint Feature and Package Designers in Visual Studio 2010 and read Packaging and Deploying SharePoint Solutions in the MSDN library.)

In order to debug this sucker we first have to add it to a page on our site. When the debugger starts up, it opens a page to the site we specified in the SharePoint Customization Wizard in the beginning. So select Site Actions in the upper left, then Edit Page. Select the Insert tab on the Ribbon and click Web Part. Select the Custom category and you should see your web part. Select it and click Add on the bottom right of the section.

image

At this point you should hit your breakpoint. Hit F11 and the query will return the low inventory so you can see the data as you design the page. The Page_Load will get called a couple times when designing the web part so keep that in mind.

Next drop down the LowInventoryWebPart menu at the top right of the web part and select Edit Web Part to open the properties. Set the Title to “Low Inventory” and click OK. On the Page tab on the Ribbon select Save to save and close the page editor. Now we’ve got a nice looking web part for browsing low inventory. Sweet!

image

Close the browser window and this will close your debugging session, recycle the IIS app pool, deactivate the feature and retract the solution automatically for you. These steps are also displayed in the Output window.

Interacting with SharePoint using the Server Object Model

Well that was pretty easy to incorporate our LOB data into SharePoint with a simple web part and a data service but what if the user sees a critically low item and wants to add an item to the Task list? It would be nice if they could do it right here. The way we interact with SharePoint in a Visual Web Part is via the SharePoint Server Object Model. There are also SharePoint client object models as well; one for Silverlight clients and one for other .NET Framework clients. But because we are on the server when we are running a web part, we have access here to the server object model.

So let’s add a TextBox and a Button to our web part that allow the user to enter tasks directly onto the Task list. Go back to design mode on the Web Part, hit enter under the GridView and and type “Create Task:” under it. From the Standard tab on the toolbox, drag a Textbox onto the form then drag a Button and set its Text property to “Add”.

Double-click on the button and we can write this code in the Button1 click event handler to add a Task:

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    'Webpart code to Add to task list
    Try
        Dim mySite As SPWeb = SPContext.Current.Web
        Dim listItems As SPListItemCollection = mySite.Lists("Tasks").Items

        Dim item As SPListItem = listItems.Add()

        item("Title") = Me.TextBox1.Text
        item("Assigned To") = mySite.AllUsers(Me.Context.User.Identity.Name)

        item.Update()
        Me.TextBox1.Text = ""
        Me.Label1.Text = "Your task has been added to the task list"

    Catch ex As Exception
        Me.Label1.Text = ex.ToString
    End Try
End Sub

The way we access the current SharePoint site by using the SPContext object and getting the Current.Web. Just like you have an HttpContext in ASP.NET development you have a SPContext in SharePoint development. So let’s test this one out. Put a breakpoint on the Button1_Click handler and hit F5 to deploy and debug. The second time around you don’t need to add the web part to the site page again but it will be refreshed with our new controls and code.

Now create a task by entering a description and click the Add button. The breakpoint will hit and you can debug the code and explore some of the server object model.

image

When you’re done, navigate to the task list to see that your task has been added.

image

This project is included in the Northwind OBA solution for VS2010 located here http://code.msdn.microsoft.com/OBANorthwind  so have a look. If you’re an ASP.NET developer just getting started with SharePoint development there’s still a lot to learn, but fortunately Visual Studio 2010 can help make an unfamiliar platform easier to approach with the right tools in hand.

Download Visual Studio 2010 Beta and read the walkthroughs here: http://msdn.com/vstudio

New MSBuild Sidekicks available

The Sidekicks have been invaluable add-ons to Visual Studio for years.  Attrice just released an update to the MSBuild add-ons.  Read more about it here: http://www.attrice.info/blog/2010/01/27/msbuild-sidekick-v3-beta-is-available/

Nice “Quick Hit” Videos about ASP.NET 4 and VS 2010

Earlier today someone pointed me at some nice “quick hit” videos that have been published that also provide quick first looks at some of the new features coming with ASP.NET 4 and VS 2010.  These videos aren’t an exhaustive list of everything new – but do provide a great way to quickly learn about many of the cool new things coming with the release. 

ASP.NET 4 Videos

You can learn more about some of the new ASP.NET 4 features by watching these 22 ASP.NET Quick Hit Videos.

image

VS 2010 Videos

You can learn more about a few of the new VS 2010 features by watching these 8 VS 2010 Quick Hit Videos.

image

ASP.NET Team Member Interviews

In addition to the feature demo videos above, you can also watch these ASP.NET team member interviews done by Scott Hanselman.  In them various ASP.NET team members talk about a few of the new features they’ve worked on.

image 

There are a lot more features coming with .NET 4 and VS 2010 not covered by all of these videos.  But hopefully the above clips provide a good way to quickly get a sense of some of the new capabilities.

The irritation of bad names

A couple of days ago I accidentally derailed the comments on Eric Lippert’s blog post about unused ”using” directives. The reason that redundant code doesn’t generate a warning in Visual Studio is that it’s what you get to start with in Visual Studio. This led me to rant somewhat about other aspects of Visual Studio’s behaviour which sacrifice long term goodness in favour of short term efficiency. Almost all the subsequent comments (at the time of writing this post) are concerned with my rant rather than Eric’s post. Some agree with me, some don’t – but it’s only now that I’ve spotted the bigger picture behind my annoyances.

All of them are to do with names and the defaults provided. I’ve blogged before about how hard it is to find a good name – it’s a problem I run into time and time again, and the ability to rename something is one of the most important refactorings around.

If you don’t know, ask

Now if it’s hard to find a good name, it stands to reason that anything the IDE can generate automatically is likely to be a poor name… such as ”Form1″, ”textBox1″ or ”button1_Click”. And yet, in various situations, Visual Studio will happily generate such names, and it can sometimes be a small but significant pain to correct it.

The situation which causes me personally a lot of pain is copying a file. For C# in Depth, I have a lot of very small classes, each with a Main method. When I’m evolving an example, I often want to take the existing code and just change it slightly, but in a new file. So I might have a file called OrderByName.cs containing a class called OrderByName. (I agree this would normally be a bad class name, but in the context of a short but complete example it’s okay.) I want to just select the file, hit copy and paste, and be asked for a new filename. The class within the file would then be renamed for me as well. As an aside, this is the behaviour Eclipse has in its Java tooling.

In reality, I’d end up with a new file called ”Copy of OrderByName.cs”, still containing a class called OrderByName. Renaming the file wouldn’t offer to rename the class, as the filename wouldn’t match the class name. Renaming the class by just changing it and then hitting Ctrl-. would also rename the original class, which is intensely annoying. You’re basically stuck doing it manually with find and replace, as far as I can see. There may be some automated aid available, but at the very least it’s non-obvious.

Now the question is: why would I ever want a file called ”Copy of OrderByName.cs”? That’s always going to be the wrong name, so why doesn’t Visual Studio ask me for the right name? It could provide a default so I can skip through if I really want to (and probably an ”Apply to all items” if I’m copying multiple files) but at least give me the chance to specify the right filename at the crucial point. Once it knows the right new filename before it’s got a broken build, I would hope it would be easy to then apply the new name to the class too.

The underlying point is that if you absolutely have to have a name for something, and there’s no way a sensible suggestion can be provided, the user should be consulted. I know there’s a lot of discussion these days about not asking the user pointless questions, but this isn’t a pointless question… at least when it comes to filenames.

If you don’t need a name, don’t use one

I’m not a UI person, so some of this section may be either outdated or at least only partially applicable. In particular, I believe WPF does a better job than the Windows Forms designer.

Names have two main purposes, in my view. They can provide semantic meaning to aid the reader, even if a name isn’t strictly required (think of the ”introduce local variable” refactoring) and they can be used for identification.

Now suppose I’m creating a label on a form. If I’m using the designer, I can probably see the text on the label – its meaning is obvious. I quite possibly don’t have to refer to the label anywhere in code, unless I’m changing the value programmatically… so why does it need a name? If you really think it needs a name, is ”label1″ ever going to be the right name – the one you’d have come up with as the most meaningful one you could think of?

In the comments in Eric’s blog, someone pointed out that being prompted for a name every time you dragged a control onto the designer would interrupt workflow… and I quite agree. Many of those controls won’t need names. However, as soon as they do need a name, prompting for the name at that point (or just typing it into the property view) isn’t nearly such a distraction… indeed, I’d suggest it’s actually guiding the developer in question to crystallize their thoughts about the purpose of that control.

Conclusion

Okay, this has mostly been more ranting – but at least it’s now on my blog, and I’ve been able to give a little bit more detail about the general problem I see in Visual Studio – a problem which leads to code containing utterly useless names.

The fundamental principle is that I want every name in my code to be a meaningful one. The IDE should use two approaches to help me with that goal:

  • Don’t give a name to anything that doesn’t deserve or need one
  • If a name is really necessary, and you can’t guess it from the rest of the context, ask the user

I don’t expect anything to change, but it’s good to have it off my chest

Type initialization changes in .NET 4.0

This morning, while checking out an email I’d received about my brain-teasers page, I discovered an interesting change to the CLR in .NET 4.0. At least, I think it’s interesting. It’s possible that different builds of the CLR have exhibited different behaviour for a while – I only have 32-bit versions of Windows installed, so that’s what I’m looking at for this whole post. (Oh, and all testing was done under .NET 4.0b2 – it could still change before release.)

Note: to try any of this code, build in release mode. Running in the debugger or even running a debug build without the debugger may well affect the behaviour.

Precise initialization: static constructors

I’ve written before about static constructors in C# causing types to be initialized immediately before the type is first used, either by constructing an instance or referring to a static member. In other words, consider the following program:

using System;

class StaticConstructorType
{
    private static int x = Log();
    
    // Force ”precise” initialization
    static StaticConstructorType() {}
    
    private static int Log()
    {
        Console.WriteLine(”Type initialized”);
        return 0;
    }
    
    public static void StaticMethod() {}
}

class StaticConstructorTest
{
    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(”No args”);
        }
        else
        {
            StaticConstructorType.StaticMethod();
        }
    }
}

Note how the static variable x is initialized using a method that writes to the console. This program is guaranteed to write exactly one line to the console: StaticConstructorType will not be initialized unless you give a command line argument to force it into the ”else” branch. The way the C# compiler controls this is using the beforefieldinit flag.

So far, so boring. We know exactly when the type will be initialized – I’m going to call this ”precise” initialization. This behaviour hasn’t changed, and couldn’t change without it being backwardly incompatible. Now let’s consider what happens without the static constructor.

Eager initialization: .NET 3.5

Let’s take the previous program and just remove the (code-less) static constructor – and change the name of the type, for clarity:

using System;

class Eager
{
    private static int x = Log();
    
    private static int Log()
    {
        Console.WriteLine(”Type initialized”);
        return 0;
    }
    
    public static void StaticMethod() {}
}

class EagerTest
{
    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(”No args”);
        }
        else
        {
            Eager.StaticMethod();
        }
    }
}

Under .NET 3.5, this either writes both ”Type initialized” and ”No args” (if you don’t pass any command line arguments) or just ”Type initialized” (if you do). In other words, the type initialization is eager. In my experience, a type is initialized at the start of execution of the first method which refers to that type.

So what about .NET 4.0? Under .NET 4.0, the above code will never print ”Type initialized”.

If you pass don’t in a command line argument, you see ”No args” as you might expect… if you do, there’s no output at all. The type is being initialized extremely lazily. Let’s see how far we can push it…

Lazy initialization: .NET 4.0

The CLR guarantees that the type initializer will be run at some point before the first reference to any static field. If you don’t use a static field, the type doesn’t have to be initialized… and it looks like .NET 4.0 obeys that in a fairly lazy way. Another test app:

using System;

class Lazy
{
    private static int x = Log();
    private static int y = 0;
    
    private static int Log()
    {
        Console.WriteLine(”Type initialized”);
        return 0;
    }
    
    public static void StaticMethod()
    {
        Console.WriteLine(”In static method”);
    }

    public static void StaticMethodUsingField()
    {
        Console.WriteLine(”In static method using field”);
        Console.WriteLine(”y = {0}”, y);
    }
    
    public void InstanceMethod()
    {
        Console.WriteLine(”In instance method”);
    }
}

class LazyTest
{
    static void Main(string[] args)
    {
        Console.WriteLine(”Before static method”);
        Lazy.StaticMethod();
        Console.WriteLine(”Before construction”);
        Lazy lazy = new Lazy();
        Console.WriteLine(”Before instance method”);
        lazy.InstanceMethod();
        Console.WriteLine(”Before static method using field”);
        Lazy.StaticMethodUsingField();
        Console.WriteLine(”End”);
    }
}

This time the output is:

Before static method
In static method
Before construction
Before instance method
In instance method
Before static method using field
Type initialized
In static method using field
y = 0
End

As you can see, the type initialized when StaticMethodUsingField is called. It’s not as lazy as it could be – the first line of the method could execute before the type is initialized. Still, being able to construct an instance and call a method on it without triggering the type initializer is slightly surprising.

I’ve got one final twist… what would you expect this program to do?

using System;

class CachingSideEffect
{
    private static int x = Log();

    private static int Log()
    {
        Console.WriteLine(”Type initialized”);
        return 0;
    }
    
    public CachingSideEffect()
    {
        Action action = () => Console.WriteLine(”Action”);
    }
}

class CachingSideEffectTest
{
    static void Main(string[] args)
    {
        new CachingSideEffect();
    }
}

In .NET 4.0, using the Microsoft C# 4 compiler, this does print ”Type initialized”… because the C# compiler has created a static field in which to cache the action. The lambda expression doesn’t capture any variables, so the same delegate instance can be reused every time. That involves caching it in a static field, triggering type initialization. If you change the action to use Console.WriteLine(this) then it can’t cache the delegate, and the constructor no longer triggers initialization.

This bit is completely implementation-specific in terms of the C# compiler, but I thought it might tickle your fancy anyway.

Conclusion

I’d like to stress that none of this should cause your code any problems. The somewhat eager initialization of types without static constructors was entirely legitimate according to the C# and CLR specs, and so the new lazy behaviour of .NET 4.0. If your code assumed that just calling a static method, or creating an instance, would trigger initialization, then that’s your own fault to some extent. That doesn’t stop it being an interesting change to spot though :)

LINQPad 2.0 Release Candidate

Download LINQPad.exe 2.00.2 RC for Framework 3.5 (see below for Framework 4.0 build)

LINQPad has undergone major reengineering to enable expansion of its provider base. The new version features first-class support for:

  • SQL Azure cloud databases
  • ADO.NET Data Services endpoints
  • SQLite databases and MySQL Enterprise and Community databases (via a library based on Matt Warren’s IQueryable toolkit)
  • Arbitrary Entity Framework providers (by specifying a custom connection string and an EDM)
  • Your own data sources (via an open extensibility model)

To handle all this, the connection dialog has been enhanced. Here’s what you now get when you click ‘Add Connection’:

Clicking ‘LINQ to SQL’ gives the familiar dialog, but with new radio buttons and controls to support Azure (and Data Services):

ADO.NET Data Services

Clicking ‘View more drivers’ displays a dialog displaying online drivers, which you can download and start using with a single click. Right now there’s a driver that leverages Matt Warren’s IQueryable toolkit: this lets you query SQLite databases (and MySQL, pending licensing) as easily as SQL Server:

The great news is that this is implemeted via a new extensibility point in LINQPad. You can use this same extensibility point to write your own drivers – for instance, to offer first-class support for querying through your favourite object relational mapper. Click here for information on writing your own driver.

The LINQPad RC is a standalone executable and can be safely used on production machines

Fabulous Adventures In Coding

What’s the difference between a destructor and a finalizer?

Today, another dialogue, and another episode of my ongoing series ”what’s the difference?”

What’s the difference, if any, between a “destructor” and a “finalizer”?

Both are mechanisms for cleaning up a resource when it is no longer in use. When I was asked this, at first I didn’t think there was a difference. But some Wikipedia searches turned up a difference; the term “destructor” is typically used to mean a deterministically-invoked cleanup, whereas a “finalizer” runs when the garbage collector says to run it.

Doesn’t that mean that the C# spec uses the term “destructor” incorrectly?

Yes, by these definitions, the C# spec gets it wrong. What we call a “destructor” in the spec is actually a finalizer, and what we call the “Dispose()” method invoked by a “using” statement is in fact a “destructor”.

The CLI spec calls the finalizer by its right name.

Why did the authors of the C# spec get it wrong?

I don’t know, but I can guess. I have two guesses.

Guess #1 is that on May 12th, 1999 there was not a Wikipedia article clearly describing the subtle difference between these two concepts. That’s because there wasn’t a Wikipedia. Remember back when there wasn’t a Wikipedia? Dark ages, man. The error might simply have been an honest mistake, believing that the two terms were identical.

Heck, for all I know, the two terms were identical on May 12th, 1999, and the difference in definitions only evolved later, as it became obvious that there was a need to disambiguate between eager/deterministic and lazy/nondeterministic cleanup methods. Anyone who has more historical perspective on this than I do, feel free to chime in here.

Guess #2 is that on May 12th, 1999, the language design committee wished to leave open the possibility that a C# ”destructor” could be implemented as something other than a CLR finalizer. That is, the ”destructor” was designed to be a C# language concept that did not necessarily map one-to-one with the CLR’s ”finalizer” concept.

When designing a language at the same time as the framework it sits atop is also being designed, sometimes you want to insulate yourself against late-breaking design changes in your subsystems. Deliberately preventing name conflation is one way to do that.

What’s your sudden obsession with May 12th, 1999 about?

The language committee’s notes for May 12th 1999 read in part:

We’re going to use the term ”destructor” for the member which executes when an instance is reclaimed. Classes can have destructors; structs can’t. Unlike in C++, a destructor cannot be called explicitly. Destruction is non-deterministic – you can’t reliably know when the destructor will execute, except to say that it executes at some point after all references to the object have been released. The destructors in an inheritance chain are called in order, from most descendant to least descendant.  There is no need (and no way) for the derived class to explicitly call the base destructor. The C# compiler compiles destructors to the appropriate CLR representation.  For this version that probably means an instance finalizer that is distinguished in metadata. 

Notice that this supports my hypothesis that the language design team was attempting to insulate themselves from becoming tied to a particular CLR term.

Configuration & Decoupled Modules

Two architectural demands for the Silverlight HVP, which are common to many larger applications, came together this week and crystallized into a design that looks to solve a couple other, unanticipated requirements.   Specifically, we knew that (1) we wanted to have configuration files and that (2) we wanted each module to be created independently of all the other modules. After some discussion, thrashing, input from some great folks at CodeMash, and further review, the design that has emerged allows us to implement two other less thought-through requirements: (3) the ability to restore the state of the application to an earlier condition and (4) the ability to save the state of the application when it is shut down.

The New Design For Configuration

All of this is much easier to understand by diving into the design that has emerged.  While the UI has not been determined, the core modules have been identified, and it is easier to conceptualize them with images; even if they don’t necessarily reflect how the modules will be presented to the user.

Function Vs. UI

Below are two sketches of potential User Interfaces for the same four objects; neither of these represents a considered UI design, but rather are here to make concrete the underlying structure that would support such disparate designs. (Click on images to enlarge)

Standard Mockup.bmml

In the standard mock-up (which may well represent the standard UI), the HVPItemsControl contains a list of all the items (videos, animations, etc.) that will be viewed in this HVPSet. 

The Current Item selected (or defaulted to)   determines the topics to be listed in the HVPLocationsControl and the hyperlinks listed in the HVPLinksControl.

Selecting a location causes the HVPPlayer Module to jump to the corresponding location. Selecting a new Item causes the HVPLocationsControl and the HVPLinks Module to fetch their new data

Selecting a link causes a new HVPSet to be created, potentially with its own Items, each of which has its own locations and links.

Distinguishing the Module from its UI

Alt Mockup

Before discussing configuration, event and state management, let’s look at a quick mock-up of another UI for these four primary modules (excluding the speculated Cloud Module)

The goal of creating this second mock-up, again, is to help wrap our heads around the difference between the functionality of the various modules, and their appearance (UI).

It should be quite easy to create a UI like this just with with templates, though no one is suggesting that this amalgam of different approaches is a serious design.

(Though, I must admit, I like the links appearing in bubbles, perhaps with a soft popping sound as they animate into existence from a point, expanding outwards).

Configuration

The requirement is that each module can be created in any order, and that no module is required, nor does any module know about any other. There are a number of ways to architect for this; though the problem is both constrained and (therefore?) simplified by the decision to create a composite application using MEF.

My strong inclination is to treat design of anything you are not about to code as a form of optimization: best left until you know what is needed. I’m a firm believer in Emerging Design, which, for me comes down to the recognition that you cannot know, in advance, what your architecture should be, because both the requirements and the design will evolve in response to the very act of building the application. 

You can, and should,  however, distinguish between a flexible architecture and a brittle one. One great way to do so is to throw ideas at the architecture and see if it has to change significantly every time you add a feature or a new way of approaching the problem. If the architecture nimbly adjusts and, better, expands on the requirement to reveal new possibilities, you are in great shape. (If it creaks and threatens to break with every new idea, then it is time to rethink!)

We have made the following decisions, to be implemented in the next three weeks:

  • MEF will be used to compose the application
  • An Event Manager (HVPEvents) will be created, and each module will register with HVPEvents when created by MEF
  • Events will signal a change in state of the current HVPSet   [footnote 1]
    • Modules will check the state object to determine what their current configuration should be
  • Configuration will be created first as objects, then persisted with Xaml   [footnote 2]
Markup Model Equals Object Model – Rob Relyea 

The rest of this posting will focus on two key ideas:

  1. Configuration and state persistence will be captured in objects and persisted with Xaml
  2. Modules announce only that their state has changed; interested modules then chek the current state.

Configuration, Objects, Xaml and Persistance

The state of a module is represented by a corresponding state object (e.g., HVPLocationState). The state of the application at any given moment is held by an ApplicationState object and represented as an HVPSet. The ApplicationState is, in turn, composed of the module state objects. Thus, the state of the application illustrated above would be represented by an HVPSet object that contains an HVPLocationState object, an HVPItemsState object and an HVPLinksState object. Note that there is no state object for the player as the player’s state is determined by the other objects (at least at this moment).

[Note, the state objects are not implemented in the current release, and are really mental placeholders for a final design. The goal, however, is to have objects that correspond to the information stored in the Xaml configuration file]

The ApplicationState object will initially only exist in memory. In time, it will be persisted either locally (local storage) or on a server, and accessed via a URL.

I’ll walk through this below, but note that this design will be implemented in stages, roughly:

  • First stage: we only know about configuration state, and that is hard-wired
  • Stage 2: we know about configuration state by reading a Xaml file and creating the objects
  • Stage 3: we know about configuration state by reading Xaml files (plural) identified by the Modules and assembling the configuration state
  • Stage 4: we can return to a previous state by storing a collection of HVPSet objects in memory, each of which consists of state objects for each module
  • Stage 5: we can persist state by writing the members of all the HVPSet objects to Xaml files.
  • Stage 6: The state of the application can be persisted by a service which returns a URL to that state. The user can then store that URL (to resume later) or send it to someone else (“Check out this very cool video and note the links to our site!”) that will allow another user to restore to the exact state that was saved, including the location in the video, the other items enqueued, the links displayed, etc.

 

Configuring Each Module

When a module is added to the application by MEF it will register itself with the HVPEvents class. [footnote 2]

Initial Configuration

The module will ask the HVPState for its own state object (e.g., the HVPLocation module will ask for the HVPLocationState object). If that object is not null, the module will use the state object to configure itself. 

When an object wishes to raise an event, it will send a message to HVPEvents which will, in turn, raise the appropriate event. The event will signal modules that subscribe to that event that they need to obtain their State object and their use of the state object will be identical to their actions in the initial configuration.

Let’s walk through a couple scenarios:

Bootstrapping when the user selects a video or set of videos

In this scenario the application has not started on the user’s machine, and the user makes a gesture (e.g., clicks on a link) to “watch” a video or an animation, or more likely an entire “experience.” In any case, the URL resolves to an HVPSet which is passed to the application on start up.

As the Application bootstraps it creates the  ApplicationState (a Singleton). The ApplicationState is given the Uri of the selected HVPSet, which returns a Xaml file. The ApplicationState asks the ConfigurationParser to convert the Xaml into an HVPSet.  In version 1, the HVPSet that is created has the Uri of the HVPItemsState.xaml file.

When MEF adds the HVPItemsModule, the HVPItemsModule requests the HVPItemsState object from ApplicationState. The AppliationState requests the HVPItemsState from the HVPState, which in turn asks the ConfigurationParser to read the HVPItemsState.xaml file and to return an HVPItemsState object which it then holds a reference to. The HVPState object also returns a copy of the HVPItemsState to the HVPItemsModule(by way of the ApplicationState object.) The HVPItemsModule then sends a message to HVPEvents which in turn raises the ApplicationStateChanged event.

The HVPLocationModule / HVPLocationState objects and the HVPLinksModule / HVPLinksState objects are created in much the same way.

When the HVPViewer is initialized, it obtains the current HVPItem from the ApplicationState which it uses to determine what type of HVPFrame to create. The HVPFrame  in turn creates the appropriate HVPPlayer which, in its turn, obtains the item using the same mechanisms.  The HVPViewer registers to obtain StateChange notifications so that if a different HVPItem is requested the correct Frame and Player can be created.

Handling User Generated Events

While an item is displaying the user can take any of the following actions:

  • Click on an item in the ItemModule
  • Click on a topic in the LocationModule
  • Click on a link in the LinksModule
  • Stop the application 
  • Request a snapshot of the current state of the application
  • Request a new set from the server (by whatever gesture the user began the application)

Clicking on an Item causes the HVPItemsModule to send a message to HVPEvents which raises the ApplicationStateChanged, which in turn causes the HVPLocation module and the HVPLinks module to re-set their state based on the current item.

Clicking on a topic causes the LocationsModule to send a message to HVPEvents which raises the ApplicationStateChanged, which in turn causes the the HVPLinks module to re-set its state and the HVPPlayer to seek to the requested location.

Clicking on a link causes the HVPLinksModule to send a message to HVPEvents which raises the ApplicationStateChanged, which in turn causes all the modules to set their state based on the new HVPSet. (Each link is tied to an HVPSet with its own set of Items).

In a version after V1, Stopping or closing the application or requesting a snapshot will (probably) cause a dialog box to open to ask the user if state should be saved, which is accomplished by having the ApplicationState save its current  HVPSet either locally or on a server, with a Uri returned which is then saved locally.

Design Simplification

In the current design the only event is the ApplicationStateChangedevent. For now, therefore, we will collapse HVPEvents into the ApplicationState object, and modules will not need to register, they will obtain the ApplicationState Instance and request that it fire the ApplicationStateChanged event.

Marker Reached, TimeObject Created, TimeReached

An earlier iteration of this design designated a number of other events that are now subsumed under the ApplicationStateChanged event, including the events needed to signal the HVPPlayer that the HVPLinks module has created a WatchedTime collection (for elapsed times at which it needs to be notified) and the ability for the HVPPlayer to notify any interested modules that a WatchedTime has arrived or that a Marker has been reached.

All of these are now handled as described above; that is, e.g., when the HVPPlayer reaches a Marker or a WatchedTime it updates the ApplicationState which in turn fires off an ApplicationStateChanged event, and the interested modules reset their own state accordingly (e.g., the HVPLinks module might add a link to its list).

———-

[1] Particular thanks to Jeremy D. Miller for helping me think this through at an Open Spaces at CodeMash.
[2] Special thanks to Rob Relyea and to Glenn Block

Open Data Protocol gör det enklare bygga REST-baserade tjänster

Open Data Protocol, eller OData som det ofta förkortas, var en av de nyheter som presenterades på PDC-konferensen i november. OData är ett öppet protokoll för att hantera frågor och uppdateringar mot datakällor som exponeras med hjälp av REST-baserade tjänster. Med öppet menas att det är publicerad under Microsoft’s Open Specification Promise och alltså är helt fritt att använda för implementeringar i andra teknikstackar än Microsofts egna (vilket också har skett – mer om det längre ner).

REST, som står för ‘Representational State Transfer’, är som bekant en arkitekturstil som beskriver hur du bygger tjänster som exponeras via URI:er, där du arbetar med  HTTP-protokollets GET, PUT, POST och DELETE-verb för att hämta, skapa, uppdatera och radera data. REST är ett mönster som blivit mer och mer populärt som ett alternativ till SOAP i tjänstebaserade arkitekturer.

Några av anledningarna till att REST har haft såna framgångar tror jag är:

  • REST-baserade tjänster är i grunden interoperabla vilket är lämpligt när man har en många olika typer av klienter.
  • Tjänsterna går att skala med befintliga lastbalanserare och cache-servrar eftersom du använder HTTP-protokollets grundmetoder.
  • Resurser går att upptäcka och borra sig ner i genom sin URI – d.v.s. adressen i sig är en beskrivning av resurserna som du kommer att hämta eller påverka – vilket gör det enkelt att förstå, testa och felsöka tjänsterna.
  • REST är tillståndslöst i sin natur vilket tvingar in dig i ett asynkront tänk – vilket i sin tur gör det enklare att bygga skalbara tjänster.

Ett problem har varit att det har saknats bra plattformsoberoende angreppsätt för att arbeta riktigt effektivt med REST-baserade tjänster. T.ex. så har det inte funnits något standardiserat sätt att beskriva datastrukturerna som tjänsterna returnerar, vilket har gjort det svårt att automatgenerera proxy-klienter samt ge Intellisense-stöd på klientsidan. Det har också saknats ett enhetligt sätt att ange filter-utryck och andra urvalsvillkor i tjänsteanropen. Ett exempel kan vara att du t.ex. vill kunna stega dig igenom ett resultatset i en datamängd.

Open Data Protocol, som i sin tur bygger på HTTP- och AtomPub-protokollen, tillför funktionalitet för att baka in metadata som beskriver den datastruktur som en REST-baserad tjänst erbjuder. Protokollet beskriver också en syntax för hur du begär att tjänsten ska filtrera det data som den returnerar. OData är egentligen inget nytt – implementeringar har tidigare funnits under benämningarna “Astoria” Protocol och ADO.NET Data Services Protocol. OData är ett sätt att samla dessa i ett enhetligt protokoll och göra det öppet tillgängligt.

Nedan är ett exempel på hur kommunikation med hjälp av OData kan se ut. Ett GET-anrop mot min Northwind-tjänst kan returnera en Atom-feed som visar vilka entiteter som min tjänst exponerar:

GET /Northwind.svc/ HTTP/1.1

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<service xml:base=http://localhost:1308/Northwind.svc/
  xmlns:atom=http://www.w3.org/2005/Atom
  xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">
<workspace>
<atom:title>Default</atom:title>
<collection href="Categories">
<atom:title>Categories</atom:title>
</collection>
<collection href="Products">
<atom:title>Products</atom:title>
</collection>
</workspace>
</service>

Genom att ange Products och ange ett id som parameter i URL:en kan jag få ut en enskild produkt:

GET /Northwind.svc/Products(1) HTTP/1.1

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://127.0.0.1:1308/Northwind.svc/" xmlns:d=http://schemas.microsoft.com/ado/2007/08/dataservices
  xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <id>http://127.0.0.1:1308/Northwind.svc/Products(1)</id>
  <title type="text"></title>
  <updated>2010-01-18T21:52:38Z</updated>
  <author>
    <name />
  </author>
  <link rel="edit" title="Product" href="Products(1)" />
  <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category" type="application/atom+xml;type=entry"
  title="Category" href="Products(1)/Category" />
  <category term="NorthwindModel.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:ProductID m:type="Edm.Int32">1</d:ProductID>
      <d:ProductName>Chai</d:ProductName>
      <d:QuantityPerUnit>10 boxes x 20 bags</d:QuantityPerUnit>
      <d:UnitPrice m:type="Edm.Decimal">18.0000</d:UnitPrice>
      <d:UnitsInStock m:type="Edm.Int16">39</d:UnitsInStock>
      <d:UnitsOnOrder m:type="Edm.Int16">0</d:UnitsOnOrder>
      <d:ReorderLevel m:type="Edm.Int16">10</d:ReorderLevel>
      <d:Discontinued m:type="Edm.Boolean">false</d:Discontinued>
    </m:properties>
  </content>
</entry>

Men genom utökningen av AtomPub-protokollet och namnrymden ‘http://schemas.microsoft.com/ado/2007/08/dataservices/metadata’ (Data Services Metadata Namespace) så beskrivs också vilka datatyper som den aktuella entiteten innehåller. Till exempel att egenskapen ‘Discontinued’ är en ‘Edm.Boolean’ (Edm står för Entity Data Model). På så sätt kan en klient använda sig av metadata för t.ex. proxy-generering, typ-check och Intellisense.

Så här kan en filtrering och sortering se ut med OData-syntax:

GET /Northwind.svc/Products/?Category=Beverages&$orderby=ProductName&$top=2&$filter=Discontinued eq false HTTP/1.1

Ovanstående uttryck skulle ge de två första produkterna som har Category ‘Beverages’ där egenskapen Discontiued är satt till ‘false’ –  sorterat på ProductName.

En sak som jag tycker är intressant med Open Data Protocol är att det redan finns ett antal icke-Microsoft implementeringar av protokollet – t.ex. finns det en Java-implementation, stöd inbyggt i WebSphere och en PHP-implementation. Bygger du REST-baserade tjänster i .NET och vill dra nytta av OData så kan du med fördel använda WCF Data Services (finns både för .NET 4 och 3.5 SP1). Men det finns också inbyggt stöd för OData i många produkter och plattformar som släppts eller är på väg att släppas – t.ex. Sharepoint 2010 och PowerPivot.

Här finns en bra FAQ om OData – själva protokollet hittar du på www.odata.org – missa inte heller Pablo Castros briljanta session om WCF Data Services och Odata från PDC-konferensen.

Hej världen!

Välkommen till WordPress. Det här är ditt första inlägg. Redigera det eller radera det. Sedan kan du börja blogga!

WordPress Themes Hosted Exchange , Hosted CRM. Hosted Sharepoint Online backup dedikerad server