Monday, 15 September 2008

Ajax Web Parts Part 2 - Web Part Connections

Posts In This Series:

Introduction - ASP.NET AJAX and Web Parts
Ajax Web Parts Part 1 - Drag and Drop
Ajax Web Parts Part 2 - Web Part Connections
Ajax Web Parts Part 3 - Dynamic Web Parts
Ajax Web Parts Part 4 - Dynamic Web Part Connections


Download the source - Part 1
Download the source - Part 2
Download the source - Part 3
Download the source - Part 4



Introduction

The first part of this series introduced the components required to perform basic Web Part drag and drop.

In that post a simple Web Part was created from the Calendar component. This was then used to illustrate how a Web Part could be moved between Web Part Zones that had been created at design time.

Although the Calendar component was useful for illustrating how a Web Part can be moved between zones, it doesn’t really give a realistic view of how Web Parts would be used in a real-world situation. For this we need something slightly more complex – a pair of Web Parts that communicate via a connection.



Click here to see what will be created.



Web Part Connections

Two Web Parts are required to form a Web Part Connection; a Provider Web Part to initiate the connection and a Consumer Web Part to receive the connection.

For our example, both of these Web Parts can be formed by creating a standard User Control and then adding it to a WebPartZone (by dragging it from the Solution Explorer window and dropping it into the WebPartZone in the Design view of the Web Form).

For simplicity the Provider part consists of only 2 items: a text box to enter a string and a button to send the string to the Consumer part. So, in the markup, the Provider is given by:






The Consumer only contains a label, to display the string that is received from the Provider. Its markup is therefore as follows:






To allow these Web Parts to communicate we must now define the connection between them. This is done by creating an interface that specifies the type and name of parameters that may be passed between the Web Parts.

In our case we are only sending a string (the text entered into the text box) from the Provider to the Consumer. The interface (in the sample download code this is defined in IWebPartInterface.cs within the App_Code directory) therefore defines that the Consumer can get a single string, called Message, from the Provider and appears as follows:


public interface IWebPartInterface
{
string Message { get;}
}



In the code-behind the User Controls must specify the part they play in the connection.

The Provider, as its name suggests, must provide the interface. It does this by having a function that returns the interface. This function is identified by using the ConnectionProvider attribute. Each end of the connection is referred to as a Connection Point. The ConnectionProvider attribute takes a parameter that assigns a name to the connection point (for our provider we’ve radically called it “ProviderConnectionPoint”).

Since, in our case, the Provider class inherits from the IWebPartInterface the member function can simply return an instance of its class (i.e. it returns this).

Finally, the Provider needs to actually return some data to give to the consumer. In our case this is simply the value that gets entered into the text box and, from the interface we’ve defined, we know that this value should be labelled as Message.

Therefore the complete code-behind of the Provider class is as follows:


public partial class User_Controls_Provider
: System.Web.UI.UserControl, IWebPartInterface
{
[ConnectionProvider("ProviderConnectionPoint")]
public IWebPartInterface GetProviderData()
{
return this;
}

public string Message
{
get { return TextBox1.Text; }
}
}



In the Consumer the ConnectionConsumer attribute is used to specify that the SetProviderData method is used to get the interface and store it into a local variable.

Once the connection has been established between the Provider and the Consumer, the Consumer can use it to set the text of its label and this is done at the pre-render stage of the page lifecycle.


public partial class User_Controls_Consumer
: System.Web.UI.UserControl
{
IWebPartInterface itsProvider = null;

[ConnectionConsumer("ConsumerConnectionPoint")]
public void SetProviderData(IWebPartInterface aProviderData)
{
itsProvider = aProviderData;
}

protected override void OnPreRender(EventArgs e)
{
if (itsProvider != null)
{
Label1.Text = itsProvider.Message;
}
base.OnPreRender(e);
}
}



Finally, the connection needs to be specified in the Web Part Manager. This needs to define which Web Part acts as the provider of the connection and which as the consumer. So, for the Web Parts we’ve defined, the markup appears as follows:




Putting this all together results in a Web Page consisting of 2 Web Parts that can be dragged between the Web Part Zones and that can communicate. Entering some text into the provider Web Part’s text box and clicking on the button results in the text appearing in the consumer Web Part, as shown below:






Click here to see this in action.



Conclusion

This post has expanded our Web Part example to show how 2 Web Parts can communicate using a Web Part Connection. Everything has still been created statically at design time. In the next post I’ll look at how these Web Parts and Web Part Zones can be created dynamically to form a tab framework.


Links


More information on Web Part Connections can be found at the following:

http://www.carlosag.net/Articles/WebParts/connectionsTutorial.aspx

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webparts.webpartconnection.aspx





Saturday, 7 June 2008

Ajax Web Parts Part 1 - Drag and Drop

Posts In This Series:

Introduction - ASP.NET AJAX and Web Parts
Ajax Web Parts Part 1 - Drag and Drop
Ajax Web Parts Part 2 - Web Part Connections
Ajax Web Parts Part 3 - Dynamic Web Parts
Ajax Web Parts Part 4 - Dynamic Web Part Connections


Download the source - Part 1
Download the source - Part 2
Download the source - Part 3
Download the source - Part 4



Introduction
In this post I'm going to describe the very basic steps required to get Web Parts drag and drop up and running from scratch. This will use a Calendar item, added to a Web Part Zone, to make a generic Web Part. This is the standard demonstration of Web Parts that has been used in a multitude of other Web Part tutorials - it's replication here is purely to get the basic components in place before moving on to other, more advanced, topics.

Click here to see what will be created.

Required Components
At present, due to the evolving nature of the subject, there are a large number of different versions of ASP.NET and its related components. These components can appear in releases with titles such as “futures”, “extensions” and “Community Technology Previews (CTPs)". As a result, one of the major challenges when working with ASP.NET is finding the appropriate set of components to use – each release appears to have its own unique fixes and quirks and, consequently, it can be difficult to find the correct combination to achieve the desired results. Hopefully ASP.NET 4.0 will fix all the bugs and tie everything together!

Therefore, when working with ASP.NET AJAX and Web Parts we will require more than the standard ASP.NET framework; extra components are needed either to add functionality or to fix problems in the current release. To begin with we will start with a standard system and add these extra components as required.

Initially, to follow along with the code in these posts, you will require 2 things:

1. Visual Studio 2008 or Visual Web Developer Express
2. The ASP.NET AJAX Control Toolkit





Creating the initial project
From the file menu, select "New Web Site" and then choose "AJAX Control Toolkit WebSite" from the list of available options:







Adding the Web Part Components
Now we need to add a few components to the page to give us something to work with.
From the toolbox, when in design or split mode, drag the following items onto the default.aspx page:
From the WebParts toolbox tab:


  • 1 x Web Part Manager
  • 2 x Web Part Zones

Then, from the Standard toolbox tab, drag a Calendar component and drop it into the first Web Part Zone - this will automatically convert the Calendar into a generic Web Part.

After the addition of these items, the default.aspx page should look as shown below (it also includes a ToolkitScriptManager which is there as a consequence of the initial project choice we made. At present this isn't being used, but will be required later.)


Before we can actually run this project, and get the drag and drop behaviour that we’re after, we need to make a small addition to the code behind.


Display Modes and Personalization
If you were to run the project in its current state, you would see one of two things - either you would get a database error, or you would see the Calendar component, but would be unable to change its position.

The reason why drag and drop is not yet possible is due to the display mode setting of the Web Part Manager. Display modes are used to define what operations can be performed on the Web Parts; the default display mode is "Browse" and this is the mode currently used by our page. In this mode it's only possible to do basic operations, such as minimize and close; it's not possible to perform drag and drop. To enable drag and drop requires, at a minimum, the display mode to be changed to "Display".

However, things aren't quite so simple. When web parts are moved on the page it's necessary to save the information about their new positions so that they can be restored to these locations the next time the page is rendered. This information is stored into a personalization table in a database. Thus, to enable the more advanced features of Web Parts, such as drag and drop, requires a database to be available. If you haven't yet got a database the easiest option is to download SQL Server Express.

To set the Web Part Manager’s display mode, add the following code into the Default.aspx.cs file:



protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// set the display mode to "Design" to allow drag and drop
WebPartDisplayMode mode = WebPartManager1.SupportedDisplayModes["Design"];
if (mode != null)
{
WebPartManager1.DisplayMode = mode;
}
}
}


If this is the first time that the page is being rendered (i.e. not a postback), then this code checks the Web Part Manager to see if the "Design" mode is contained in its list of supported display modes. If it is, then it sets this to be the current display mode.


We now have everything in place to enable drag and drop. Press F5 to run the project and hopefully you should see the following output:

If you have run this using Internet Explorer, drag and drop functionality should now be enabled:
- when the cursor is hovered over the title bar it should change to the directional cursor and clicking and holding on the Calendar web part's title bar should enable it to be selected and dragged to the second Web Part Zone.

However, with the current release of ASP.NET 3.5, if you have run this in a browser other than IE (e.g. Firefox), then the chances are that the drag and drop won't be working - to fix this we need to make another modification.


Web Part Drag and Drop in Firefox
For some reason Microsoft have chosen not to include the fix for Firefox (and other non-IE) browsers in the latest releases of the ASP.NET framework. To get things working in all browsers requires the download of the
Microsoft ASP.NET Futures (July 2007) Release - obviously this is a technology preview release and is therefore not supported for production sites - however, the alternative is to not have drag and drop support for all non-Microsoft browsers, so you need to choose which of these is the most important to you.

Once this futures release has been downloaded, its components need to be added to your Visual Studio toolbox. To do this, you need to do the following steps:

  1. In the toolbox window, move the cursor into the bottom tab pane and right click to bring up the context menu. From this choose "Add Tab" and create a new tab for the futures release.

  2. From within this new tab pane, select "Choose Items.." from the right-click context menu.

  3. In the dialog that appears choose browse and locate the futures DLL (mine was downloaded to C:\Program Files\Microsoft ASP.NET\ASP.NET Futures July 2007\v1.3.61025\3.5).Click on OK once all the components of this DLL have been selected. All these components should then be added to the new tab of the toolbox, as shown below.



As you can see, the toolbox now contains both a WebPartManager and WebPartZone that have been added from the Futures release. All we need to do now are replace the standard versions of these that we'd added already with these new Futures versions and that should fix our Web Parts drag and drop for all browsers.



AJAX Enabling The Web Parts
We've only one thing left to do, and that's remove the annoying postbacks that occur when the Web Parts are moved. To do this we simply need to wrap everything in an UpdatePanel from the AJAX Extensions tab of the toolbox. We already have a ScriptManager present from the AJAX Control Toolbox - however, for consistency, I've chosen to remove this and replace it with the standard version. Once everything is in place, the body of my default.aspx file now looks as follows:







Click here to see this in action.


This concludes the introduction to Web Parts. In future posts I'll expand apon this simple project to show how Web Parts can be combined with both the ASP.NET AJAX framework and the ASP.NET AJAX Toolkit Tab component.


Thursday, 5 June 2008

ASP.NET AJAX and Web Parts

Posts In This Series:

Introduction - ASP.NET AJAX and Web Parts
Ajax Web Parts Part 1 - Drag and Drop
Ajax Web Parts Part 2 - Web Part Connections
Ajax Web Parts Part 3 - Dynamic Web Parts
Ajax Web Parts Part 4 - Dynamic Web Part Connections


Download the source - Part 1
Download the source - Part 2
Download the source - Part 3
Download the source - Part 4



Introduction
In my quest to create a database capable of storing anything and everything (see earlier posts), my attention over the last few months has turned from the back end to the front end UI.

One obvious way to display a set of disparate information is to use a Web Portal style framework - a set of widgets (small window components) within a tab framework - the tabs can be used to represent the general categories and each widget can be used to display a sub-set of information for that category. Since I’m coming from an ASP.NET background, Web Parts sounded like a perfect fit for the implementation of these widgets, and the Tab Control, from the ASP.NET AJAX Toolkit, sounded like the ideal way to wrap all these Web Parts together.

In theory, the creation of this Web Portal sounded like it would be a breeze - just drop a few Web Part Zones onto the Tab Control, and populate them with the Web Parts to show information from each category. In reality, as usual, things turned out to be not quite so simple. Over the next few posts I’m going to describe the creation of a simple version of this Web Portal and highlight the problems, and workarounds, involved with each stage.

To start I’ll be describing the very basics of getting Web Parts up and running, before moving onto some more complex issues, such as dynamically generating the Web Parts and creating new tab pages on demand.
The content of these posts won’t really provide any information that can’t be found elsewhere, however I hope that by bringing it all together, into a single place, that this will be of benefit to some - certainly it would have helped me. As mentioned, most of the stuff concerning the dynamic creation of Web Parts can be found in other locations and, when I can remember where I obtained information from, I’ll try and reference these other sources. One things that these posts won’t be are in-depth overviews of either Web Parts or ASP.NET AJAX - a basic knowledge of these is assumed - if you’d like more information on either of these topics, I can recommend the books shown in the reading list.

Tuesday, 3 July 2007

Using SemWeb with MySQL

Getting SemWeb to work with MySQL is pretty much the same as for SQLite (see the last post). Again, using the news.rdf file from Mozilla, the command line to enter data into the MySQL database now becomes:

rdfstorage news.rdf --out "mysql:rdf:database=news;username=test"

This assumes that a new database (schema) called "news" has been created in MySQL and that a user "test" exists that doesn't require a password (both these things can be done using the MySQL Administrator UI).

Initially running this command line in the installed version of the SemWeb\bin directory results in the following error being generated:

System.IO.FileNotFoundException: Could not load file or assembly 'MySql.Data, Version=1.0.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' or one of its dependencies. The system cannot find the file specified.


This error means that the MySQL.Data.dll is missing, so the first step is to get this from MySQL ADO.Net Data Provider 5.0.7

After placing this DLL in the bin directory and running the command line again, the following error will appear:

System.IO.FileLoadException: Could not load file or assembly 'MySql.Data, Version=1.0.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)


In this case the important part is the "manifest definition does not match the assembly reference" bit - as happened with the SQLite DLL, this MySQL DLL is newer than the version that was used to build the SemWeb.MySQLStore.dll and so the 2 DLLs are incompatible. We need to rebuild this SemWeb DLL.


The steps to do this are as follows:

  • Open the SemWeb solution in Visual Studio
  • Add a new project of type "Class Library" and called "SemWeb.MySQLStore"
  • Delete the default "Class1.cs" that gets added to the project
  • Choose to add an existing item to the project and pick "MySQLStore.cs" from the SemWeb\src directory
  • Add a reference to the "MySQL.Data.dll " that should already be in the SemWeb\bin directory
  • Add a reference to the SemWeb project
  • In the project properties, set the output path to the SemWeb\bin directory

These are the exact same steps that were required for the SQLiteStore DLL (although obviously referencing different files). However, building the MySQLStore DLL now results in the following compiler error:

The type or namespace name 'MySqlConnection' could not be found (are you missing a using directive or an assembly reference?)

To fix this error the following needs to be added to the top of the MySQLStore.cs file:

using MySql.Data.MySqlClient;


So the complete set of using directives at the top of the file should now appear as:


using System;
using System.Collections;
using MySql.Data.MySqlClient;
using System.Data;

The project should now rebuild successfully and the new SemWeb.MySQLStore.dll should now appear in the SemWeb\bin directory.

Unfortunately this still isn't the end of the process - running the command line again results in the following error:

MySql.Data.MySqlClient.MySqlException: Table 'news.rdf_statements' doesn't exist

The DLL is now ok, its just that the database that its creating has a few problems; inspecting the database in MySQL Administrator shows that the "rdf_literals" and "rdf_entities" tables have been created but the "rdf_statements" table hasn't been made.

Setting the SEMWEB_DEBUG_SQL environment variable (type "set SEMWEB_DEBUG_SQL=1" at the command prompt) and then running the command line again generates some debug information (alternatively put a break point on the "
CreateTable" function in the SQLStore.cs file and run the program in the debugger, after first setting up the command line arguments in the project properties). The error generated is:

System.FormatException: Input string was not in a correct format.

This is caused by the SemWeb database "Open" function (from MySQLStore.cs) querying the version of the database and then trying to set this into the .NET Version class; however, the version string returned from my version of MySQL is "5.0.41-community-nt" and this doesn't match with the expected .NET version string format, which is expecting only integers seperated by a period character ('.') - hence an error is thrown on the first call to "Open" and so the creation of the first database table ("rdf_statements") fails.

To fix this I've just put a try-catch around the setting of the version string, so basically I just ignore when the version can't be set.




private void Open()
{
if (connection != null)
return;
MySqlConnection c = new MySqlConnection(connectionString);
c.Open();
connection = c; // only set field if open was successful

using (IDataReader reader = RunReader(@"show variables like 'version'"))
{
reader.Read();
try
{
version = new Version(reader.GetString(1));
}
catch(Exception e)
{
if (Debug) Console.Error.WriteLine(e.Message);
}
}
}


Finally, rebuilding the SemWeb DLL and re-running the command line successfully adds the RDF to the database:

news.rdf 0m0s, 81 statements, 1728 st/sec
Total Time: 0m2s, 81 statements, 30 st/sec

Monday, 2 July 2007

Using SemWeb with SQLite

As mentioned in the previous post I've had a few problems getting SemWeb, the C# RDF library, to persist data to a database. Here I describe the steps I've had to follow to get things working.

I've been using Visual Studio on Windows - I suspect that these problems may not exist when using Mono on Linux.

I'm using the following versions:


SQLite

Following the approach described in the SemWeb documentation, I first tried to set up a database connection to a SQLite database.

Following the SemWeb documentation I performed the following steps:

  • Placed the "sqlite3.dll" (from the SQLite download) into my windows System32 directory
  • Added the "Mono.Data.SqliteClient.dll" from the the Mono install directory "Mono-1.2.4\lib\mono\2.0" into my SemWeb\bin directory
  • Downloaded the sample RDF file from http://www.mozilla.org/news.rdf
  • Entered the specified command line at a DOS prompt in the SemWeb\bin directory:
    rdfstorage.exe news.rdf --out "sqlite:rdf:Uri=file:news.sqlite;version=3"
  • Pressed return and stood well back.

I was greeted with the following:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileLoadException: The located assembly's manifest definition with the name 'Mono.Data.SqliteClient' does not match the assembly reference.

Basically my Mono SQLite adapter was newer than the version that the SemWeb.SqliteStore.dll had been built with.

Unfortunately the SemWeb Visual Studio solution doesn't come with a SemWeb.SqliteStore project, so the following steps are required:

  • Open the SemWeb solution in Visual Studio
  • Add a new project of type "Class Library" and called "SemWeb.SqliteStore"
  • Delete the default "Class1.cs" that gets added to the project
  • Choose to add an existing item to the project and pick "SQLiteStore.cs" from the SemWeb\src directory
  • Add a reference to the "Mono.Data.SqliteClient.dll" that should already be in the SemWeb\bin directory
  • Add a reference to the SemWeb project
  • In the project properties, set the output path to the SemWeb\bin directory

I also rebuilt the SemWeb and RDFStorage projects (after setting their output directories to the bin directory). Once built I re-ran the command line and this time obtained the expected result:


news.rdf 0m0s, 81 statements, 1036 st/sec
Total Time: 0m1s, 81 statements, 42 st/sec



Next time I'll describe the steps I've had to follow to get SemWeb up and running with MySQL.

Topic Maps, OWL and RDF

It's been quite a while since my last post. This has mostly been due to spending a large amount of time playing with some Topic Map (the Ontopia Omnigator) and OWL (Protege) software. Both of these are excellent applications and I was especially impressed by the ability of OWL to form advanced object relationships.

However, at the end of all this research, I think that neither Topic Maps nor OWL are suitable for my purposes; yes, both can perform complex classifications and describe advanced relationships between classes but, for my purposes of creating a heterogeneous database, I only require simple classifications and relationships. Therefore using either of these technologies would probably be like taking the proverbial hammer to a nut. For me, a stronger argument against using these technologies is that, at this moment in time, neither is freely available for C# - the language that I'd like to work with.

So my requirements are a technology that can describe simple classifications and relationships and that is freely available in C#. The one application that seems to match these requirements is Joshua Tauberer's SemWeb - an RDF library for C#. The RDF and RDFS support provided by this package can perform categorisation and describe the relationships between objects to a level suitable for my requirements. An added bonus is that this library is still under active development - version 1.0 was only released on the 10th June 2007 (unlike the other C# RDF library Drive - the web page of which had actually expired the last time I looked).

This doesn't mean to say that SemWeb is perfect - like most things I've encountered on this journey, using SemWeb is not as straightforward as it could be. The main reason for this is that SemWeb has been developed on Mono, as opposed to Microsoft's Visual Studio that I want to use. As a result of this the supplied Visual Studio solutions are incomplete (I needed to refer to the makefiles to create the required projects) and the package currently doesn't support SQL Server, the Express version of which I'd been using for some other areas of this project (such as user administration). I've therefore now switched databases to use MySQL and am now struggling to add and retrieve some RDF data from this. I'll give more details of this struggle in the next post.

Wednesday, 16 May 2007

RDF - An alternative to Topic Maps?

In my last post I described how Topic Maps appeared to be a possible mechanism for creating a flexible database, capable of storing a range of different, and possibly unrelated, items - a heterogeneous database. However, as I also mentioned previously, a couple of things worried me about Topic Maps; namely that work in the area seems to have gone a bit quiet in the last couple of years and, secondly, that there appears to be quite a large European bias to the companies and institutions working in the field - not that this is a bad thing, but what are everyone else up to?

These two things were playing on my mind, so rather than rushing headlong into Topic Maps, I decided to take a step back and spend a bit more time investigating other possible solutions. This search revealed that there is another possible solution to the problem - RDF - the Resource Description Framework (I'd already suggested in my last post that this could be a possibility). Indeed RDF and Topic Maps appear to cover very similar ground and, from an initial study of the available information, it's hard to decide between the two. It may be that subtle differences exist between the two technologies but my initial impression is that they are pretty much going head-to-head against each other – another VHS versus Betamax, but with probably slightly less interest from the general public.

So what are the actual differences between RDF and Topic Maps and which technology is the most suitable for my purposes? As with Topic Maps, the documentation for RDF is rather sparse and also seems to mostly be a couple of years old - the only book I could find that described both subjects was The Explorer's Guide to the Semantic Web, published in 2004. While this provided a good overview of both technologies, it didn't really cover them at a low enough level for my needs and, by the end, I was still left uncertain of the differences in the two. In addition, RDF has other related technologies - namely RDFS (RDF Schema) and OWL (Web Ontology Language - which surely should be called WOL, although this would have reduced the oportunities to publish books with bird covers) and I felt that these weren't covered in enough detail. The only thing for it was to dig a bit deeper into each subject.

RDF, RDFS and OWL
The definitive (and about the only) text on RDF is Shelley Power's Practical RDF. This book did give low level descriptions of RDF, RDFS and OWL and I'd definitely recommend it for anyone interested in RDF. My only criticism would be that the chapters describing RDF tools are now a bit out of date (the book was published in 2003) and I found quite a few typos and mistakes in the RDF examples - a new edition of the book is surely required. However, by the end, I felt that I'd gained enough knowledge to pursue RDF a bit further.

I think I now understand how RDF, RDFS and OWL fit together. My interpretation is that RDF is a mechanism that can describe simple relationships (subject-predicate-object expressions, known as triples e.g. apples have the colour green). RDF can be serialized using RDF\XML (i.e. an XML based language can be used to describe the RDF relationships). RDF Schema can then be used, in much the same way as XML Schema (XSD) are used with XML, to describe the contents and structure of the RDF, allowing relationships to be created. OWL is effectively built on top of RDFS, extending it to allow the generation of complex class and sub-class relationships.

I'm still not sure about the differences in Topic Maps and RDF (the RDF book didn't cover Topic Maps), so I think the only thing for it is to play with the two technologies. I'll let you know how it goes in the next post.