# Sunday, 09 July 2006

I found out about this new page on ASP.NET, thanks to PeteL and Brian Goldfarb: By the Community, For the Community.

The By The Community, For the Community samples series will create ASP.NET samples that are in high demand. These samples will not be created by Microsoft but instead by a select group of ASP.NET community member MVPs. You can see their bios below.

On a regular basis, starting Friday July 7th, we will publish a list of potential samples and allow the community to vote on which sample they are most interested in seeing developed. After the voting ends, the select MVPs will then create the sample using best practices. The samples will be published and then linked to from this page on www.asp.net.

So go out and vote for the stuff that you want these guys to create! Personally I love this idea. There are a lot of smart people out there with an MVP status and they're getting more attention. Just think of the Wrox book MVP hacks for example. The ASP.NET forums also have a bunch of MVP people hanging around to help out other people.

Grz, Kris.

Sunday, 09 July 2006 12:14:02 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 07 July 2006

dasBlog is a decent blogging engine originally created by Clemens Vasters. A nice thing that not many people seem to be aware of is that you can easily extend it by creating custom macros. Such a custom macro isn't anything else than just a class library that you can hook into your copy of dasBlog and use it later on in one of the available templates that make up the website.

I couldn't really find a lot of information about this, so I decided to create my own article about the subject that also puts in the solutions I found. 
Also I would like to show the code that I use in my current installment that's reusable directly for other dasBlog users.

Creation:

So, as I already mentioned, creating macros is just like creating a class library. So lets fire up vs.net, create a new project and in the templates choose Class library like in Figure 1. The name of the project is also important when we will be configuring dasBlog to let it know about the existence of our macros. I chose MydasBlogMacros but you can choose your own name of course.

dasBlogMacro_01.png">dasBlogMacro_01_th.png" border=0>
Figure 1: Create a new project based upon the Class Library template.

If you haven't downloaded the code for dasBlog now's a good time to do so. You can download the bits from the official site(1) or you can use the guideline to get the latest bits and pieces(2) like I did.

Now we have to add 3 references in order to be able to create our custom macro. You do this by right clicking in the Solution Explorer of Visual Studio.NET on the References node. Take a look at Figure 2 to choose System.Web, and Figure 3 to choose 2 assemblies that are from dasBlog itself. These 2 are newTelligence.DasBlog.Runtime and newTelligence.DasBlog.Web.Core. The result is shown in Figure 4.

dasBlogMacro_02_01.png" border=0>
Figure 2: locate and choose System.Web

dasBlogMacro_02_02.png" border=0>
Figure 3: Navigate to the bin folder of the compiled bits of dasBlog and select the needed assemblies.

dasBlogMacro_solexpl.png" border=0>
Figure 4: After adding the needed references.

In Figure 4 you can also see that I deleted the default Class1.cs file and added a new class with the name Macros.cs. This is the only class we'll need for the moment. Here's the code for the Macros class:

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 using System.Web.UI;

    5 using newtelligence.DasBlog.Runtime;

    6 using newtelligence.DasBlog.Web.Core;

    7 

    8 namespace MydasBlogMacros

    9 {

   10     public class MyMacros

   11     {

   12         protected SharedBasePage sharedBasePage;

   13         protected Entry currentEntry;

   14 

   15         public MyMacros(SharedBasePage page, Entry entry)

   16         {

   17             sharedBasePage = page;

   18             currentEntry = entry;

   19         }

   20 

   21         public virtual Control EmailIt(string linkText, string cssStyle)

   22         {

   23             if (this.currentEntry != null)

   24             {

   25                 string link = this.currentEntry.Link != null

   26                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   27 

   28                 return new LiteralControl("<a href=\"mailto:?subject=" + this.currentEntry.Title +

   29                     "&body=I found this to be a great read: " + link +

   30                     ". Hope you like it too.\" class=\"" +

   31                     cssStyle + "\">" + linkText + "</a>");

   32             }

   33 

   34             return new LiteralControl("");

   35         }

   36 

   37         public virtual Control Delicious(string linkText, string cssStyle)

   38         {

   39             if (this.currentEntry != null)

   40             {

   41                 string link = this.currentEntry.Link != null

   42                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   43 

   44                 return new LiteralControl("<a href=\"http://del.icio.us/post?url=" + link

   45                     +  "&title=" + this.currentEntry.Title + "\" class=\"" + cssStyle + "\">"

   46                     + linkText + "</a>");

   47             }

   48 

   49             return new LiteralControl("");

   50         }

   51 

   52         public virtual Control Digg(string linkText, string cssStyle)

   53         {

   54             string link = this.currentEntry.Link != null

   55                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   56 

   57             return new LiteralControl("<a href=\"http://www.digg.com/submit?url=" + link +

   58                 "\" class=\"" + cssStyle + "\">"

   59                 + linkText + "</a>");

   60         }

   61 

   62         public virtual Control Technorati(string linkText, string cssStyle)

   63         {

   64             if (this.currentEntry != null)

   65             {

   66                 string link = this.currentEntry.Link != null

   67                     ? this.currentEntry.Link : Utils.GetPermaLinkUrl(this.currentEntry);

   68 

   69                 return new LiteralControl("<a href=\"http://www.technorati.com/search/" +

   70                     this.currentEntry.Title +

   71                     "\" class=\"" + cssStyle + "\">"

   72                     + linkText + "</a>");

   73             }

   74 

   75             return new LiteralControl("");

   76         }

   77     }

   78 }

Note that the signature in the constructor is required in order to let the macros work!
Besides the constructor I created 4 methods, which will be the macros eventually, the first one EmailIt is for creating a link with the url of the current item in the body so someone can easily mail it to someone whom (s)he thinks will also be interested in the article. The other 3 are for well known web 2.0 services: del.icio.us, digg and technorati.

The methods/macros take all 2 input parameters: the string to appear in the link and the css style that will go in the class attribute of the rendered tag. Separating content and layout has several benefits: it's easy to update in a single place and an external .css file can be cached on the client.

After compiling the source code, preferably in Release mode, and after that open windows explorer and navigate to where the .dll file is created. By default this will be the place where you created your project and in there the subfolders /bin/Release. Now copy the .dll file to the /bin subfolder of the dasBlog solution (this is the same folder where you got your references from).

Configure dasBlog:

We created our macros assembly, dropped it in the /bin folder of the dasBlog folder, but we still need to configure dasBlog in such a way that it knows of the existance of our macros. This is entirely done in the web.config file that can be found in the root folder of dasBlog. Open it with your favorite IDE and uncomment the following line at the top of the web.config:

<section name="newtelligence.DasBlog.Macros" type="newtelligence.DasBlog.Web.Core.MacroSectionHandler, newtelligence.DasBlog.Web.Core" />

Now navigate to the tag <newtelligence.DasBlog.Macros>, uncomment it and add this line:

<add macro="mymacros" type="MydasBlogMacros.MyMacros, MydasBlogMacros"/>

Remember I told in the previous part that you could name your solution somewhat else, well here that name comes into play. If you take a look at the previous line you can see this combination: type="TypeName, Name of the assembly". TypeName in this case is NameSpace.ClassName. The name in the macro attribute, in this example mymacros will be used when we want to use a specific macro.

Use the macro in your template:

So at this point we created our macros, configured dasBlog that they exist. Now comes the part where we embed, or better use, our macros so they become visible in the what a visitor can see by altering the templates in the themes. dasBlog ships with several themes out of the box and people can switch between them. You can however push visitors to only have one theme available by deleting the rest of the themes. If you don't this you'll need to do the next steps for every theme if you want those themes to also have your macros available.

Navigate to the theme folder of choice. There you'll see several .css files and 3 files that have the extension .blogtemplate. Because the macros will be used for every item, they contain specific information for a specific item, open the itemTemplate.blogtemplate file. Here you can call a macro with the following syntax:

<%EmailIt("Email it!", "mailLinkStyle")|mymacros%>.

The call can be easily identified, it's the first macro in our example EmailIt. The method takes 2 parameters. After the method call you see the | followed by the name we provided in the macro attribute when we configured the web.config. I also created a new external .css file where I put the specific styles. After that I imported the newly created file into the base.css file with this statement: @import url("mymacros.css");

Resources:

- (1): dasBlog download.
- (2): Compiling the dasBlog source code.
- The class FooMacros in the dasBlog total solution.
- Creating dasBlog macros.

 

Well that's it for this article. I hope you found it interesting and if you create new macros yourself or have questions feel free to use the Comments field to let me know.

Grz, Kris.

kick it on DotNetKicks.com

Friday, 07 July 2006 19:42:12 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [8]  | 

I just installed the latest binaries of dasBlog. If you like to know how to get the latest source code yourself I like to point out to this excellent post: Re-Post of "Compiling the DasBlog Source Code" from DasBlog.info. Also be sure to use the package.bat file at the root of the downloaded bits because publishing, using vs.net 2005, doesn't seem to work out that very well.

I also created several macros, a great feature to have IMHO, of which you can see the result in every post at the bottom. I include links to email, add to delicious, digg or technorati. It's my plan to create an article about this soon.

Grz, Kris.

Friday, 07 July 2006 14:50:51 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 30 June 2006

Today, in the afternoon, I went to the first part, the next one's tomorrow, about Visual Team System 2005 an event by VISUG of which I'm a member. Thanks to the people from Microsoft we also got a new book to read for free: Wrox' Professional Visual Studio 2005 Team System.

Wrox Professional Visual Studio 2005 Team System

The presentation is given by Steven Wilsens, whom is a Team System MVP and will be joining Microsoft in a while.

I'm looking forward to the next part of the event.

Grz, Kris.

Books | Tools | VS.NET
Friday, 30 June 2006 21:23:17 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
Friday, 30 June 2006 20:29:27 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Dynamic updatepanels, bugfixes, ...

I just read it on Nikhil's blog and downloaded it from the the Atlas site.

Details of the new CTP:

UpdatePanel:

  • UpdatePanels can be added to a page dynamically throughout the page lifecycle, including UpdatePanels inside templates. UpdatePanels now also work inside WebParts, and WebParts can be inside UpdatePanels.
  • UpdatePanel will preserve cookies set during an async postback when Response.Redirect() is called. This fixes Login control scenarios where an authorization cookie is set and the user gets redirected to the previous page.

Networking:

  • ServiceMethod uses default error handler if none specified.
  • XsltBridgeTransformer now works with VirtualPathProviders
  • DBNull.Value now should be serialized as null
  • ServiceReferences now support optional InlineProxy attribute for generating service proxies in the page rather than through a serviceurl/js script reference.
  • Fix for scenarios where web service proxy contained the wrong port (webfarms, port forwarding)

Drag and Drop:

  • Drag and drop will no longer produce debug output
  • Interactive HTML elements (input, button, textarea, select, label, anchors with an href) can no longer be dragged directly

Miscellaneous Changes:

  • Date.toFormattedString improvements
  • Client-side data: SaveData fix for strongly-typed DataSets

 

I for one hope that the RTM version is coming close.

Grz, Kris.

Friday, 30 June 2006 19:57:28 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, 29 June 2006

Get it while it's hot: http://www.microsoft.com/downloads/details.aspx?familyid=4C1A8FBE-FB6A-47AC-867D-BB1F17E477EE&displaylang=en.

Be sure to first uninstall previous versions of the beta before you install this one. Also check out the announcement on the IEBlog.

Grz, Kris.

IE
Thursday, 29 June 2006 21:14:35 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, 28 June 2006

Most people that use C# are quite familiar with the if() expression and the (?:) conditional/ternary operator. In C# 2.0, the Visual C# team introduced another operator that's less known: the ?? or null coalescing operator. A quick demo explains how to use it. The result can be seen in Figure 1:

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 

    5 namespace ConsoleApplicationNullableTypes

    6 {

    7     class Program

    8     {

    9         static void Main(string[] args)

   10         {

   11             int? input = null;

   12 

   13             IfStatements(input);

   14 

   15             // Now fill up the nullable input with some value.

   16             input = 99999;

   17 

   18             IfStatements(input);

   19 

   20             Console.ReadLine();

   21         }

   22 

   23         /// <summary>

   24         /// Show the 3 different ways to write the same if functionality in C# 2.0.

   25         /// </summary>

   26         /// <param name="input"></param>

   27         private static void IfStatements(int? input)

   28         {

   29             int result;

   30             // Scenario 1, normal if statement

   31             if (input.HasValue)

   32                 result = input.Value;

   33             else

   34                 result = 200;

   35 

   36             Console.WriteLine("Scenario 1, result: " + result.ToString());

   37 

   38             // Scenario 2, using the conditional/ternary operator

   39             result = input.HasValue ? input.Value : 200;

   40 

   41             Console.WriteLine("Scenario 2, result: " + result.ToString());

   42 

   43             // Scenario 3, using the null coalescing operator new to C# 2.0.

   44             result = input ?? 200;

   45 

   46             Console.WriteLine("Scenario 3, result: " + result.ToString());

   47             Console.WriteLine();

   48         }

   49     }

   50 }

The 3 different manners of writing the same test. Scenario 1, line number 31, is the normal if statement. Scenario 2 uses the conditional/ternary operator and just like in scenario 1 the new method HasValue is used to check if the nullable type has a value. If so then one could fetch the value by using the Value property on the nullable type.
Scenario 3, line number 44, uses the new null coalescing operator which is only available in C# 2.0.

Since I started developing with C# 2.0 in May 2005 I used to use the code like described in scenario 2 until I found out about the null coalescing operator. I find it easier to read and to use in my code. But because I found out that not too many people seem to be aware of this new gem in the C# 2.0 language I wanted to show it off in an article.


Figure 1: The result of the test.

I also blogged about using testing serious with nullable types in the past: Be sure to put in some default value when testing with Nullable types in .NET 2.0.

Grz, Kris.  

kick it on DotNetKicks.com

Wednesday, 28 June 2006 20:59:22 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, 25 June 2006

Most controls are just drag & dropped on a webform or handcoded by a developer in the source view of the document. Although these controls can display dynamic data, for example coming from a database, the controls on the webform themselves remain static. In some scenario's however you want dynamically added controls. For example if a certain authenticated user views the page you want to show more information, or depending on a certain choice you want to load a Repeater control with data or a DateTime control. In this article I instantiate a RadioButtonList control, add it to a PlaceHolder control and wire up the SelectedIndexChanged event of the RadioButtonList instance. Listing 1 shows the C# version and Listing 2 the VB.NET version. Either version is equivalent and it's quite easy to compare both of the code snippets since both have the same equivalent code on the same line.

Listing 1: C# version:

    1 <%@ Page Language="C#" %>

    2 

    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    4 

    5 <script runat="server">

    6     protected override void OnInit(EventArgs e)

    7     {

    8         base.OnInit(e);

    9 

   10         // Instantiate a RadioButtonList control

   11         RadioButtonList rbl = new RadioButtonList();

   12 

   13         rbl.AutoPostBack = true;

   14         rbl.ID = "rblID";

   15 

   16         // Wire up the eventhandler

   17         rbl.SelectedIndexChanged += new EventHandler(rbl_SelectedIndexChanged);

   18 

   19         // Add the items

   20         rbl.Items.Add(new ListItem("One", "1"));

   21         rbl.Items.Add(new ListItem("Two", "2"));

   22         rbl.Items.Add(new ListItem("Three", "3"));

   23 

   24         rbl.DataBind();

   25 

   26         PlaceHolder1.Controls.Add(rbl);

   27     }

   28 

   29     void rbl_SelectedIndexChanged(object sender, EventArgs e)

   30     {

   31         // Get the control and cast it to the

   32         // appropriate type. In our case a RadioButtonList.

   33         RadioButtonList c = (RadioButtonList)FindControl("rblID");

   34         Label1.Text = c.SelectedItem.Text;

   35     }

   36 </script>

   37 

   38 <html xmlns="http://www.w3.org/1999/xhtml" >

   39 <head runat="server">

   40     <title>Untitled Page</title>

   41 </head>

   42 <body>

   43     <form id="form1" runat="server">

   44     <div>

   45         <asp:PlaceHolder ID="PlaceHolder1" runat="server" /><br />

   46         <asp:Label runat="server" ID="Label1" />

   47     </div>

   48     </form>

   49 </body>

   50 </html>

Listing 2: VB.NET version:

    1 <%@ Page Language="VB" %>

    2 

    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    4 

    5 <script runat="server">

    6 

    7     Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)

    8 

    9 

   10         ' Instantiate a RadioButtonList control

   11         Dim rbl As New RadioButtonList

   12 

   13         rbl.AutoPostBack = True

   14         rbl.ID = "rblID"

   15 

   16         ' Wire up the event handler

   17         AddHandler rbl.SelectedIndexChanged, AddressOf rbl_SelectedIndexChanged

   18 

   19         ' Add the items

   20         rbl.Items.Add(New ListItem("One", "1"))

   21         rbl.Items.Add(New ListItem("Two", "2"))

   22         rbl.Items.Add(New ListItem("Three", "3"))

   23 

   24         rbl.DataBind()

   25 

   26         PlaceHolder1.Controls.Add(rbl)

   27 

   28     End Sub

   29 

   30     Protected Sub rbl_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)

   31 

   32         ' Get the control and cast it to the

   33         ' appropriate type. In our case a RadioButtonList.

   34         Dim c As RadioButtonList = DirectCast(FindControl("rblID"), RadioButtonList)

   35         Label1.Text = c.SelectedItem.Text

   36 

   37     End Sub

   38 

   39 </script>

   40 

   41 <html xmlns="http://www.w3.org/1999/xhtml">

   42 <head runat="server">

   43     <title>Untitled Page</title>

   44 </head>

   45 <body>

   46     <form id="form1" runat="server">

   47         <div>

   48             <asp:PlaceHolder ID="PlaceHolder1" runat="server" /><br />

   49             <asp:Label runat="server" ID="Label1" />

   50         </div>

   51     </form>

   52 </body>

   53 </html>

On line 11 the RadioButtonList is instantiated. After that it's given an ID and the AutoPostBack property is set to true (line numbers 13 & 14).
Then we wire up the event that'll be handled when a certain selection is made, remember we set the AutoPostBack property to true so once another choice than the current is made an automatic postback to the server will occur. Note the different syntax for C# and VB.NET to wire event handlers on line 17.

At this moment we already have a RadioButtonList instance, wired up the SelectedIndexChanged event, added 3 items to it and databound these items (Lines 20 to 24) but at this moment it's still not visible to the enduser since it was not already put on the page. ASP.NET provides a dedicated control for this: the PlaceHolder control. You can place this control somewhere on your webform and later on use it to hang dynamic controls to. Another convenient control for this is the Panel control. Adding our RadioButtonList to the PlaceHolder control is done on line 26.

We can now render our webform in a browser and upon checking a radiobutton in the list an automatic postback occurs, goes through the code of adding the RadioButtonList again to the page in the Page_Init/OnInit event again, which is necessary because the page has completely forgotten about the existance of it after the previous rendering. After that the rbl_SelectedIndexChanged event gets handled.
In this event we first need to obtain the correct control based upon its ID property with the FindControl method. This method returns an instance of a Control class, which is the base class of all controls in ASP.NET. Once obtained we need to cast it back to the proper class, which is in this case a RadioButtonList. Once cast the Text property of the SelectedItem is used to fill up the Text property of the Label control.

Grz, Kris.

Sunday, 25 June 2006 14:13:21 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, 24 June 2006

You know that your collegue has created a class with interesting method that you like to reuse in your ASP.NET 2.0 web project but your project is in C#. Instead of waisting time to rewriting the whole chunk of code that your collegue wrote you can simply reuse the code. The only need is to create a couple of subfolders, putting your classes, C# and VB.NET, in these separate subfolders and put some extra configuration in the web.config file.

So for example you add these subfolders to the App_Code folder: CSharp and VB.

In the web.config you put these lines in the <compilation> element:

  <system.web>

    <compilation debug="true">

      <codeSubDirectories>

        <add directoryName="CSharp"/>

        <add directoryName="VB"/>

      </codeSubDirectories>

    </compilation>



  </
system.web>

Another nice thing about this is that you could also use it to organise your classes somewhat better. For example you can create several subdirectories which hold business classes that belong together and make them known in the <codeSubDirectories> element.

Grz, Kris.

Saturday, 24 June 2006 18:49:25 (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |