This is a reminder: I post my blog postings on a new location. My latest post is about the reporting services extension for Sharepoint that I previously wrote about.
I have moved my weblog. The new location is: http://www.teuntostring.net
You can point your feed readers to http://www.teuntostring.net/blog/atom.xml
This is a reminder: I post my blog postings on a new location. My latest post is about the new version of the Gantt chart web part I just released.
I have moved my weblog. The new location is: http://www.teuntostring.net
You can point your feed readers to http://www.teuntostring.net/blog/atom.xml
Or to http://www.2rss.com/atom2rss.php?atom=http://www.teuntostring.net/blog/atom.xml if your reader does not support Atom feeds.
It's about a year and a half ago now that I started my blog. Back then, I chose for hosting it at DotNetJunkies for a number of reasons:
- I wanted my blog to be part of a larger community of development oriented blogs
- I wanted a full blown weblog engine, but not host my own Windows web server
- I liked the .Text engine
Lately, I became more and more uneasy with the services of DotNetJunkies. I have always really appreciated the free service and I understand that the bills must be paid, but I feel that the advertisements that they insert in my weblog pages are too intrusive and (this is the most important point) they slow down the pages considerably.
Since the .Text engine was replaced by CommunityServer, the deal for me as a content provider has become worse. In the migration, most of the comments on my pages where lost. The usability of the admin pages has decreased, the engine rips my HTML apart and removes a lot of extra mark-up that I wanted to add. What bothered me most was that there is no good way left to show source code (especially source code containing many angle brackets as do HTML and XML). The final push came from this article by Jacob Nielsen. Especially point number ten about owning your own domain name. I decided that I really want to own the domain name of my blog. Most visitors come in via Google anyway, so being part of the DotNetJunkies community is not that valuable after all.
Soooo, I registered the TeunToString.net domain and am now using Blogger to post my messages there and I must say: Blogger has come a long way. It is very mature and now provides most of the functionalities of a PHP or ASP.NET based engine, but using only static HTML on your page (which rocks performance-wise). I will keep all of the content in the DotNetJunkies blog online so people who made bookmarks can still use them. I will also keep posting small reminders to the blog when I post a new article on the new one.
Lots of thanks to DotNetJunkies for the provided free service. I really appreciated it and I am sure that you did the .NET development community a big favor. I'm moving on now and have to pay for my hosting.
Notice: a newer version of this web part has been published. Read and download here.
I promised a month ago that I would post a web part for charting WSS data into a Gantt chart. Well, here it is. It looks somewhat like this:

The part allows you to specify a list and view to render. You select the fields from the view that will indicate the start and end date of an item. The third required field is the title field. Because the part works with view fields, you can also use calculated fields to specify the start date, end date or title of the item.
Because I was too lazy to create a custom designer, you have to enter the names of the list, view and fields in a textbox. When you specify incorrect values, the part will show you the available options in it's error message.
So you want to use it? I put up a zip file containing both the sources and binaries. I haven't made an installer, but I suppose that most of you know what to do with a dll and dwp file. In your web.config you'll have to add a line for trusting the part like this:
‹SafeControl Assembly="Duynstee.GanttChart.WebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a66e9ace203d5f7" Namespace="Duynstee.GanttChart.WebPart" TypeName="*" Safe="True" />
The web part is actually more of a sample of using the underlying GanttCharting library. This will render VML that can be directly included into the HTML (IE only!). The charting library has some features that are not used by the web part, but that you may want to build on:
- aggregation: each GanttItem can have a collection of sub-items. Items with sub-items will be rendered accordingly (see sample in this post)
- links: each item has a LinkUrl property that will be placed on the item. You could have the item link to the edit page of the item
- color: you can color each item as you wish
Download here
It has been a long time since my last posting. It has been a busy period and the stuff I was working on wasn't suitable or ready enough to blog about. But I'm back now!
This post presents a sample solution for rendering a list of items with start dates and end dates into a Gantt chart format using only HTML and VML. VML is the vector based graphics language supported by MS Internet Explorer. I know: not cross-browser, but it suited my needs. Once SVG is well supported, minor changes would be necessary to port it to SVG.
I am working on a web part that can render the contents of a WSS list as a Gantt chart more or less like this (click the image for a real VML sample).
The part is not yet fully functional, but it will allow you to specify a list and view from your team site. Then by specifying which fields represent the start and end dates of tasks, the part has all necessary iformation for rendering the chart. The part that I haven't figured out yet is the grouping and nesting of tasks. As you can see in the sample, the rendering of hierarchical tasks is working, but the nasty part is to follow the groupings as specified in the WSS view.
Example: If you have a list with tasks, it should be possible to define a view that sorts the items and groups them first by project phase, then by assigned team member. The Gantt chart should be able to follow these groupings and display them in the chart. The grouping bar could then be used to toggle the visibility of underlying taks.
The part is not mature enough to post the code, but I will do so within a few weeks. I might even write an article about the inner workings.
I'm trying to create a web part that will display some data in a nice graphic way and I figured that VML would fit my bill. It's not cross-browser, but so is SharePoint, so what the heck. After all, Google Maps does the same, so I guess it's not off-limits anymore :).
VML is just a little bit of XML in the namespace urn:schemas-microsoft-com:vml. Along the lines of HTML extensibility as suggested in the XHTML recommendations. Problem here is that the namespace must be declared. In all of the VML samples, the VML namespace is declared on the HTML tag. If you do that, it works fine. But as I am building a web part and not the whole page, I cannot change the HTML tag of the page. So I thought I would just set the xmlns:v attribute on the container element for my shapes, but this doesn't seem to work. It requires the xmlns attribute to be on the HTML tag and nowhere else. I also tried setting the namespace from script, but without success.
Anyone has any suggestions/tips on how to tackle this? I am pretty sure that I've seen web parts using VML before.
In some of my postings, I present you out there with code. Until recently, I used a very nifty client-side code formatting solution to make it look really pretty. Some time ago, this stopped working, because the good people at DotNetJunkies.com upgraded from .Text to CommunityServer. I can see why this is necessary, but it makes my life a lot more complicated in certain ways. The syntax coloring solution uses TEXTAREA tags and client-side script. To prevent Cross-Site-Scripting attacks, CS allows only certain HTML tags in postings and strips all unexpected attributes as well. Exit code.
So, I decided to go the official XHTML way and place my code inside ‹XMP> tags. This works fine, but when I want to show XML code to you, the reader, it was still stripped away, because CS decides that it might be malicious HTML. Again, I see why, but still... what a pain. So my latest trick for showing you code is basically a canonicalisation attack: I change the [first character of an XML tag] in the code for a ‹. It is Unicode 2039 (Alt + 0139) and looks like an angle bracket, but isn't. now when you copy code from my page, it will not work, because it may look like XML, but it isn't. Sorry for that.
Recently, I posted a question about what happened to the IField, IRow and ITable interfaces that were available in the System.Web.UI.WebControls.WebParts namespace in .NET beta1 and the CTPs. I found it: IField has become IWebPartField, IRow became IWebPartRow, etc...
Interestingly, you are now supposed to pass in a delegate when you retrieve the value from the connection provider. I suppose that this is a mechanism to alert the consumer of changes occurring after the retrieval of the value? Documentation is not available yet.
I received some feedback on the Sharepoint extension article that I would like to share (I had to change < to [ in the code to get CommunityServer to display it):
Hi,
Thanks for sharing this great code. I encountered 2 problems and could find some workaround:
1) Columns with a number data type would throw an exception on a French Machine due to the impossibility to convert xml number automatically because of the decimal sign (which is "," in french). I guess it may also be the case in other languages. I used this workaround :
if ( col.DataType == typeof(Single) )
newRow[col] = XmlConvert.ToSingle(val);
else
newRow[col] = val;
2) GetListItems return data base on the default view if no view is specified. If the default view has some filter, you will collect a filtered list of items. I used this workaround:
XmlElement query = ListInfoNode.OwnerDocument.CreateElement("Query");
query.InnerXml ="[WHERE>[GT>[FIELDREF Name='\"ID\"' />[VALUE Type='\"Counter\"'>0[/VALUE>[/GT>[/WHERE>";
Frédéric LATOUR
About the second remark: that is a great trick, Frédéric! Thanks for sharing.
Now about the converting of numerics in non-english cultures. I think that the XML returned by the Sharepoint web service is not using English or American formatting, but rather the InvariantCulture. Now rather than making different conversions for different types (have you considered Double, DateTime, etc...), I would prefer to let the framework do the figuring. I think that everything will work out fine if you set the CurrentCulture of the thread to CultureInfo.InvariantCulture while copying data from the XML to the DataRow. I haven't had the time to test yet, but give it a try:
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
Don't forget to set your culture back to it's original setting.
POSTSCRIPT:
I have tested this situation now and it seems indeed to be solved by setting the current culture to InvariantCulture. Before the foreach loop (the one that copies fields from XML to the datatable), you insert this code:
System.Globalization.CultureInfo oldCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
and after the loop, you set you preferred culture back:
System.Threading.Thread.CurrentThread.CurrentCulture = oldCulture;
Ready!
When you want to create connectable web parts in ASP.NET 2.0, the preferred way to pass information is by specifying an interface with one or more properties. You can read up on how it works in this article by Carlos Aguilar Mares (based on beta 1). The nice thing of using interfaces is that you can have an IStringValue interface that just returns a string value and have an IZipCode interface deriving from IStringValue without adding or overriding any members. Of course, a zip code is a string, but a string is not always a zip code. This way, you can use zip code providers to feed both zip code consumers and consumers of string values.
To allow my connection providers to be connected to your connection consumers, they must be based upon the same interface for passing information. To make it easy for third party developers to connect to each others web parts, in beta 1 Microsoft included a small number of very simple interfaces. The most basic of them all was IField, which allowed you to pass an object (any object). They also included IParameters (set of name-value pairs), IRow (collecion of objects) and ITable (collection of isomorphic IRows). If your part does something very specific, you should specify your own interfaces, to make sure that only parts providing the right kind of info can connect to yours. But if you want your part to work with as many other parts as possible, you want to settle on a widely known interface, preferably from the framework.
Now in beta 2, all of these basic interfaces seem to have disappeared. Why is that? You can easily create these interface yourself, of course, but my interface would then be different from yours and parts from different vendors could never connect (well, you could start writing connection transformers for every combination, but that's another story).
I received a question from a reader asking how you can set a filter on the items returned from a list. Suppose you want to show only the Defects with status Active or Issues with Impact > 3? We cannot set the where clause, as we don't have a SQL statement. The data extension presented in the article always returns all rows.
Luckily, the Report Designer offers features to sort and filter the data returned before inserting it into the report. This is how to do it:
1. In Report Designer (in VS.NET) open your report on the Data tab. Select the ... button next to the list of datasets:
2. This will open the DataSet dialog. On the Filter tab, you can build expressions to filter the data. You can enter fixed values, but the expression builder will also help you to use global settings and passed parameters from the user in your filter.
This dialog allows you to do many more things to your data, like adding calculated columns. Check here.
This post refers to my article on reporting with Reporting Services over WSS Lists.
The extension presented in the article works fine in the Report Designer in Visual Studio, but it turns out that deploying it to the server requires some extra work. A problem you will encounter is that when you try to access your report through the Reporting Services website, it will give you an error like this:
Reporting Services Error
- An error has occurred during report processing. (rsProcessingAborted) Get Online Help
- Query execution failed for data set 'dataset_name'. (rsErrorExecutingCommand) Get Online Help
- Request for the permission of type System.Net.WebPermission, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.
The problem here is that the Reporting Services engine does not trust our extension code. For more on Code Access Security in .NET, check out this MSDN article. We can tell it to trust our dll by editing the file rssrvpolicy.config that you will find in the C:\Program Files\Microsoft SQL Server\MSSQL\Reporting Services\ReportServer directory. It contains XML defining a number of CodeGroups and their corresponding trust levels. We just add this code snippet at the end of the list of CodeGroups:
Note that we specifiy our exact dll to be trusted. For new extensions you may add, you'll have to add these to the list of CodeGroups as well.
The FullTrust level is rather crude of course. You could define another named permission set that has exactly the required permissions for this extension (network access).
Also: I chose to specify which code to trust using the file location (UrlMembershipCondition). Some people say you'd better sign your assembly with a strong name and trust the strong name (StrongNameMembershipCondition). I am not a very big fan of strong naming and I would suggest resorting to this way only if you really need it. After all: people who can replace your dll in the bin directory can probably also tamper with the rssrvpolicy.config file. More on what's wrong with strong naming.
Comment spam is getting worse. I'm getting really annoyed. And I cannot really do much, as my blog is hosted by dotnetjunkies.com. I've been tinkering on a small tool that would at least allow me to select a whole batch of comments and then delete them all. Finding all comments of your blog and presenting them in a selectable form is easy. Problem is that it is so ___ing hard to remove comments over HTTP.
The SOAP interfaces do not seem to support this, so I thought of just automating Internet Explorer from a tool. Event that is really hard with dotText. The Feedback.aspx page works with complex postbacks. In the old times where all applications would be passing ID's on the querystring, it would have been peanuts to emulate a user deleting a long list of comments by ID, but postbacks are a lot harder to emulate.
DotnetJunkies.com, pleeeease implement a simple CAPTCHA on the comment forms?
I haven't got a clue what's taking Microsoft so long putting up the sample code for
my article on Reporting over SharePoint lists. For the time being, you can download it from my site.
Check it out.
Several people have been asking me recently if Blogger support in Finch would we available soon. Well, today I have good news. I just published a file release to SourceForge with a new version of Finch that has (some) support for the Atom API. The Atom implementation has not been tested with any other service but Blogger. As the Blogger implementation is known to be slightly different from the standard, this means that Finch 1.1 probably does not work with other Atom blog engines. But it does work for Blogger!
Download the installer here
When you want to use Finch with your Blogger blog, follow these directions:
- In your Blogger setup, enable “Publish site feed“ on the Settings|Site feed tab
- Make sure that after publishing, the Atom XML file is indeed available on your web server
- In Finch go to Tools|Options and set the web service URL to the URL of the Atom feed on your site
- In the Credentials tab, enter your Blogger credentials
- Tap OK and try to Sync Down
You can manage only one blog through Finch, even if you have multiple blogs in Blogger.
Request for support: if you have or know of a blogging service that exposes the Atom API and that I can use for free to test, please let me know. I'm pretty sure that the Atom API implementation I have built works well only with Blogger's implementation. And as they don't use categories, I haven't implemented those either. Their implementation of passing credentials doesn't follow the spec at all. I would really help if I could test against multiple implementations.
The Microsoft site still doesn't offer the Dutch version online, but as the hard copy magazine has already been sent out, I suppose they do not mind me putting the English translation online now.
I just received the latest issue of .NET Magazine (which is a developer publication from Microsoft in Dutch). It contains an article by yours truly entitled "Rapporteren over SharePoint-lijsten met een Reporting Services Extension" (Reporting over SharePoint lists with MS Reporting Services). I am currently translating the article in English and will publish it through this blog soon.
A link to the electronic version and code download will follow shortly. I will also respond to any questions and remarks on the article through this blog.
UPDATE: Here it is
It has been possible for a few years now to include drag-drop functionality in browser-based applications. It is still tricky to make it work cross-platform (meaning IE & FireFox & Safari to me), but libraries to help do this are freely available as well. I personally like the X library from cross-browser.com (drag-drop example).
When you are a javascript enthusiast, that is all fine and sorted out, but what if you prefer to work with ASP.NET and all it's nice server controls, strong-typed programming model? You would really expect this kind of functionality to be available in out-of-the-box, but it isn't. Not in the 1.1 release from 2003 and not in the forthcoming 2.0 release. There is some dragging functionality implemented in the Web Part Framework, but this cannot be used for non-WebPart functionality.
But ASP.NET can always easily be extended, so presumably, someone has already implemented some kind of server control that adds drag-drop to other elements on the page? Well, maybe someone has, but I couldn't find it. I was imagining the following:
- A server control named DragDropManager, that is invisible at runtime
- In VS.NET, the property browser show a DragObjects collection and a DropTargets collection. In DragObjects, you can add references to the other controls on the page or user control. Maybe you can also indicate what subelement of the draggable element is the “handle“. You can also specify a CSS classname that will be added to the style of the element during dragging.
- The DropTargets collection can also be filled with references to elements. DropTargets have a hover-class, which is added to the style while something is dragged over the target that could be accepted by the target
- Drag objects and drop targets could also know the concept of content types. Drag objects of content type X can only be dropped on a drop target that accepts X
- When an object is dropped on a target, an event is fired. This can be a client-side event or a server-side event (as configured on the drop target).
Did anyone ever come across this component? Free or paid? It seems very usefull in implementing web applications with rich features. I do know of some frameworks for Rich Internet Applications that include drag-drop, but these typically don't work nicely with standard existing ASP.NET server controls. Still, I don't see a reason why this couldn't work.
PS. The envisioned DragDropManager would of course be even cooler when implemented as an ExtenderProvider, so you could set all of the drag related proerties on the object-to-drag itself. But it seems that ExtenderProviders do not work well for web forms in VS.NET 2003 (more info and a fix).
I have finally decided that this is it. Finch is now stable and can be used against several blogging back-ends. I know that there are several implementations out-there that will not work fine with Finch, but when they conform to the MetaWeblogAPI, it should. I also started an online manual for Finch here. If you want to manage your blog from your PPC, download Finch 1.0!
Now that stabilizing is over, I can focus on new functionality. The main two features I will start working on are:
- Atom API support. This will allow all Blogger users to use Finch (and I like the APi and it looks stable now)
- Picture uploading. I have had several requests for adding some sort of picture support. I am thinking of a menu option in the posting editor that will upload a .jpg to a configured FTP server and include an <img> link to it in the postings content.