sharing about .NET and technology RSS 2.0
 Monday, September 24, 2007

A new version of SyntaxColor4Writer has been released, version 0.25. It has been updated with the newest release of Windows Live Writer Beta 3 and CodeHighlighter 4.0.0049 from Actipro.

Monday, September 24, 2007 8:40:00 PM (Romance Standard Time, UTC+01:00)  #    Comments [1] -

 Wednesday, July 11, 2007

A new version of SyntaxColor4Writer has been released, version 0.24. It has been updated with the newest release of Windows Live Writer Beta 2 and CodeHighlighter 4.0.0048 from Actipro. There are also some minor changes in the layout of the sidebar.

SyntaxColor4Writer024

Please leave a comment to let me know if there are any issues and/or feedback!

Wednesday, July 11, 2007 12:44:02 AM (Romance Standard Time, UTC+01:00)  #    Comments [1] -

 Thursday, March 22, 2007

Last weekend I visited CeBIT 2007 in Hannover. We rented a house for the weekend in Steinhude which is not far from CeBIT and can easily be reached by car and train. If you are looking to stay overnight in Steinhude I would recommend this house, all comfort is available (TV, shower, kitchen, etc.).

Like every year, there were lots of brands and new products to discover. One of the cool things at CeBIT, is that you can gather a lot of gadgets :). An eyecatcher was this modding project for the World Cyber Games 2007 which is a 200 hours project! And I found that server rack of IBM also impressive.

    

One of the things that really touched me - a trip down memory lane -, was a working Commodore 64 of the good old days. There was a room that showed some computer history.

    

If I remember correctly, I have had the following computers with which I grew up, and I have to admit, it was mainly for playing games :-)

And when I came of age, I switched to the traditional personal computer. But I must say that there is really nothing compared to those old skool arcade games, such as

Thursday, March 22, 2007 11:35:27 PM (Romance Standard Time, UTC+01:00)  #    Comments [5] -

 Thursday, March 01, 2007

CSLA.NET framework from Lhotka contains a lot of mechanisms for adding validations and business rules. Through CSLA.NET you can easily provide your own custom rules. Enterprise Library v3.0 now also contains a validation application block (VAB) that can be used through attributes and even from a configuration file.

The two validation mechanisms of validation are complementary. This can be done by adding a custom rule that uses the ValidationFactory of the VAB. This means we have something like:

Copy Code
public class VABRules { public class VABRuleArgs : RuleArgs { private string _ruleset; public string Ruleset { get { return _ruleset; } } public VABRuleArgs(string propertyName) : this(propertyName, null) { } public VABRuleArgs(string propertyName, string ruleset) : base(propertyName) { _ruleset = ruleset; } } public static bool VABValid<T>(object target, RuleArgs e) { Validator<T> validator = ValidationFactory.CreateValidator<T>(((VABRuleArgs)e).Ruleset); if (validator == null) return true; ValidationResults results = validator.Validate(target); if (results == null) return true; foreach (ValidationResult result in results) { if (result.Key == e.PropertyName) { e.Description = result.Message; return false; } } return true; } }

Having the VAB rule we simply need to decorate our properties with the validation attributes of VAB and an override of the AddBusinessRules method is needed to take into account the VAB rules. For example we can define a customer business object as follow:

Copy Code
[Serializable()] public class Customer : Csla.BusinessBase<Customer> { private int _id = 0; private string _firstName = string.Empty; private string _email = string.Empty; private int _rewardPoints; private string _countryCode = string.Empty; [Browsable(false), System.ComponentModel.DataObjectField(true, true)] public int Id { get { CanReadProperty("Id", true); return _id; } } [NotNullValidator(MessageTemplate="First Name may not be empty")] [StringLengthValidator(1, 60, MessageTemplate = "First Name must be between 1 and 60 characters long")] public string FirstName { get { CanReadProperty("FirstName", true); return _firstName; } set { CanWriteProperty("FirstName", true); if (!_firstName.Equals(value)) { _firstName = value; PropertyHasChanged("FirstName"); } } } [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*")] public string Email { get { CanReadProperty("Email", true); return _email; } set { CanWriteProperty("Email", true); if (!_email.Equals(value)) { _email = value; PropertyHasChanged("Email"); } } } [Int32RangeValidator(0, 1000000, MessageTemplate = "Rewards points cannot exceed 1,000,000")] public int RewardPoints { get { CanReadProperty("RewardPoints", true); return _rewardPoints; } set { CanWriteProperty("RewardPoints", true); if (!_rewardPoints.Equals(value)) { _rewardPoints = value; PropertyHasChanged("RewardPoints"); } } } [NotNullValidator(MessageTemplate = "Country may not be empty")] public string CountryCode { get { CanReadProperty("CountryCode", true); return _countryCode; } set { CanWriteProperty("CountryCode", true); if (!_countryCode.Equals(value)) { _countryCode = value; PropertyHasChanged("CountryCode"); } } } protected override object GetIdValue() { return _id; } protected override void AddBusinessRules() { ValidationRules.AddRule(VABRules.VABValid<Customer>, new VABRules.VABRuleArgs("FirstName")); ValidationRules.AddRule(VABRules.VABValid<Customer>, new VABRules.VABRuleArgs("Email")); ValidationRules.AddRule(VABRules.VABValid<Customer>, new VABRules.VABRuleArgs("RewardPoints")); ValidationRules.AddRule(VABRules.VABValid<Customer>, new VABRules.VABRuleArgs("CountryCode")); } }
Thursday, March 01, 2007 2:39:25 PM (Romance Standard Time, UTC+01:00)  #    Comments [6] -

 Thursday, February 22, 2007

In many enterprise applications there is the need that, regardless on which control you have the focus, that you can hit the 'Enter' and/or 'Esc' key to perform a default action. This behaviour is also common to web applications. On the Form control you find properties like AcceptButton and CancelButton, whereas the UserControl doesn't have these properties. The code below contains an AcceptButton and CancelButton that allows you to define a default action when the Enter or Esc key is pressed respesctively.

Copy Code
public class UserControlEx : System.Windows.Forms.UserControl { private Button _acceptButton; private Button _cancelButton; public event EventHandler<EventArgs> AcceptEvent; public event EventHandler<EventArgs> CancelEvent; [Browsable(true)] public Button AcceptButton { get { return _acceptButton; } set { _acceptButton = value; } } [Browsable(true)] public Button CancelButton { get { return _cancelButton; } set { _cancelButton = value; } } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (msg.WParam.ToInt32() == (int)Keys.Enter) { OnAcceptEvent(EventArgs.Empty); if (_acceptButton != null) _acceptButton.PerformClick(); } if (msg.WParam.ToInt32() == (int)Keys.Escape) { OnCancelEvent(EventArgs.Empty); if (_cancelButton != null) _cancelButton.PerformClick(); } return base.ProcessCmdKey(ref msg, keyData); } protected virtual void OnAcceptEvent(EventArgs args) { if (AcceptEvent != null) AcceptEvent(this, args); } protected virtual void OnCancelEvent(EventArgs args) { if (CancelEvent != null) CancelEvent(this, args); } }
Thursday, February 22, 2007 10:32:31 PM (Romance Standard Time, UTC+01:00)  #    Comments [3] -

 Thursday, January 25, 2007

In some enterprise applications you need to show geographical data such as countries and postcodes. Most of the time you need it for a registration page, where the user need to fill in the country and postcode/area.

Geonames is a free geographical database that contains over 8 million geographical names and it can be accessed through a number of webservices. For example the url http://ws.geonames.org/countryInfo? gives an xml with all countries, whereas the following request http://ws.geonames.org/postalCodeSearch?placename=be gives us all postcodes for a particular country (e.g. Belgium).

Most likely you need two dropdown lists, one for countries and one for postcodes, where the postcode dropdown is dependent from the country dropdown list. This is a very good example to introduce AJAX by using the CascadingDropdown that is included in ASP.NET AJAX.

To implement this functionality we need to implement two methods on a webservice, namely GetCountries and GetPostalCodesByCountry. The GetCountries simply returns all countries sorted by name and looks like this:

GeonamesService.asmx.cs - Copy Code
[WebMethod] public CascadingDropDownNameValue[] GetCountries() { List<CascadingDropDownNameValue> list = new List<CascadingDropDownNameValue>(); CountryItemCollection countries = IStaySharp.Geonames.GeonamesService.GetAllCountries(); for (int i = 0; i < countries.Countries.Length; i++) { list.Add(new CascadingDropDownNameValue( countries.Countries[i].CountryName, countries.Countries[i].CountryCode)); } list.Sort(CompareCascadingDropDownNameValueByName); return list.ToArray(); }

Note that the list need to be converted to an array of CascadingDropDownNameValue objects. Note that we also sort the list by implementing a delegate named CompareCascadingDropDownNameValueByName.

GeonamesService.asmx.cs - Copy Code
private static int CompareCascadingDropDownNameValueByName(CascadingDropDownNameValue x, CascadingDropDownNameValue y) { if (x == null && y == null) return 0; else if (x == null && y != null) return -1; else if (x != null && y == null) return 1; else return x.name.CompareTo(y.name); }

The other webservice method, called GetPostalCodesByCountry, need to retrieve all postcodes for a particular country. The signature of the method is very strict. The parameter names must be named 'knownCategoryValues' and 'category', otherwise it will fail!

GeonamesService.asmx.cs - Copy Code
[WebMethod] public CascadingDropDownNameValue[] GetPostalCodesByCountry(string knownCategoryValues, string category) { List<CascadingDropDownNameValue> list = new List<CascadingDropDownNameValue>(); StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues); if (kv.ContainsKey("Country")) { string countryName = kv["Country"]; PostalCodeItemCollection postalCodes = IStaySharp.Geonames.GeonamesService.GetPostalCodes(countryName); for (int i = 0; i < postalCodes.PostalCodes.Length; i++) { list.Add(new CascadingDropDownNameValue( string.Format("{0} ({1})", postalCodes.PostalCodes[i].PostalCode, postalCodes.PostalCodes[i].Name), postalCodes.PostalCodes[i].PostalCode)); } } list.Sort(CompareCascadingDropDownNameValueByName); return list.ToArray(); }

In order to complete the webservice, the attribute ScriptService (line 3) need to be included so that a client javascript proxy can be generated. You can test this by calling your webservice like this http://localhost:9999/GeonamesService.asmx/js.

GeonamesService.asmx.cs - Copy Code
1 [WebService(Namespace = "http://tempuri.org/")] 2 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 3 [System.Web.Script.Services.ScriptService()] 4 public class GeonamesService : System.Web.Services.WebService 5 { 6 ... 7 }

Finally we only need to add two CascadingDropDown controls on our aspx page with the following settings:

Default.aspx - Copy Code
<asp:ScriptManager ID="scriptManager" runat="server" /> <asp:DropDownList ID="countriesDropDown" runat="server"/> <ajaxToolkit:CascadingDropDown ID="countriesCascadingDropDown" TargetControlID="countriesDropDown" Category="Country" PromptText="Please select a country" LoadingText="[Loading countries...]" ServicePath="/GeonamesService.asmx" ServiceMethod="GetCountries" runat="server"/> <br/><br/> <asp:DropDownList ID="postalCodesDropDown" runat="server"/> <ajaxToolkit:CascadingDropDown ID="postalCodesCascadingDropDown" TargetControlID="postalCodesDropDown" Category="PostalCode" PromptText="Please select postalcode" LoadingText="[Loading postalcodes...]" ServicePath="GeonamesService.asmx" ServiceMethod="GetPostalCodesByCountry" ParentControlID="countriesDropDown" runat="server"/>

The source code can be downloaded here: IStaySharp.AJAXSample.rar (332,56 KB)

Thursday, January 25, 2007 2:13:28 AM (Romance Standard Time, UTC+01:00)  #    Comments [2] -
 | 
 Wednesday, January 24, 2007

Scott Guthrie is coming for a presentation on February 1st. The session will take place at Utopolis Mechelen. Please subscribe to the event through the VISUG site. Two presentations will be given, namely:

  • First Look at Visual Studio  and ASP.NET 'Orcas'
  • ASP.NET 2.0 and ASP.NET AJAX Tips and Tricks

See you there!

Wednesday, January 24, 2007 12:27:56 AM (Romance Standard Time, UTC+01:00)  #    Comments [0] -

 Sunday, January 14, 2007

Yep, version 1.0 of the Web Client Software Factory has been released. Release 2 is expected around the end of June 2007.

Sunday, January 14, 2007 5:22:56 PM (Romance Standard Time, UTC+01:00)  #    Comments [1] -

 Wednesday, January 10, 2007

Virtual PC 2007 RC1 has been released, and can be downloaded on the Microsoft Connect site, if you participated in the beta tests. The main new features are:

  • Support for Windows Vista™ as a host operating system
  • Support for Windows Vista™  as a guest operating system
  • Support for 64-bit host operating systems
  • Support for hardware-assisted virtualization
  • Built-in support for network installations

More details about the release notes can also be downloaded on the Microsoft Connect site.

Wednesday, January 10, 2007 12:04:03 AM (Romance Standard Time, UTC+01:00)  #    Comments [0] -
 | 
 Saturday, December 30, 2006

The Validation Application Block (VAB) of the upcoming Enterprise Library v3, uses attributes to describe validations. This gives us for example the opportunity to generate ASP.NET validators based on the attributes decorated on the properties.

Take for example the NotNullValidator of VAB, this can be translated to a RequiredFieldValidator, whereas the RegexValidator can be translated to RegularExpressionValidator. You can go further with the NotNullValidator and mark required fields with a different backcolor and adding an asterix (*) to the end of the control.

I am big fan of the DetailsView control, you can simply bind a DataSource control to it, and it will automatically provide you with a caption to each control and two-way binding. Below you find an example how you can extend the BoundField control, that investigates the NotNullValidator attribute of VAB. Note that I am currently extending it for the other set of validators and in a more OO way. More info will follow later.

BoundFieldEx.cs - Copy Code
public class BoundFieldEx : System.Web.UI.WebControls.BoundField { public override void InitializeCell( DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex) { base.InitializeCell(cell, cellType, rowState, rowIndex); if ((((rowState & DataControlRowState.Edit) != DataControlRowState.Normal) && !this.ReadOnly) || ((rowState & DataControlRowState.Insert) != DataControlRowState.Normal)) { TextBox textBox = null; if (cell != null && cell.Controls.Count > 0) textBox = cell.Controls[0] as TextBox; if (textBox != null) { Type dataItemType = null; if (DataBinder.GetDataItem(base.Control) != null) dataItemType = DataBinder.GetDataItem(base.Control).GetType(); if (dataItemType != null) { ValidatorAttribute attribute = IsRequired(dataItemType, base.DataField); if (attribute != null) { string textBoxID = this.DataField; textBox.ID = textBoxID; RequiredFieldValidator validator = new RequiredFieldValidator(); validator.ControlToValidate = textBoxID; validator.ID = string.Concat("RequiredValidatorOf", textBoxID); validator.Display = ValidatorDisplay.Dynamic; validator.ErrorMessage = attribute.MessageTemplate; cell.Controls.Add(validator); } } } } } private ValidatorAttribute IsRequired(Type dataType, string property) { PropertyInfo propertyInfo = dataType.GetProperty(property); if (propertyInfo != null) { foreach (Attribute attribute in propertyInfo.GetCustomAttributes(true)) { if (attribute is NotNullValidatorAttribute) return attribute as ValidatorAttribute; } } return null; } }

Now you create a custom business object, called Customer, and bind it to the DetailsView through an ObjectDataSource.

Customer.cs - Copy Code
public class Customer { private string _firstName; private string _lastName; [NotNullValidator(MessageTemplate="Firstname cannot be empty")] public string FirstName { get { return _firstName; } set { _firstName = value; } } [NotNullValidator(MessageTemplate="Lastname cannot be empty")] public string LastName { get { return _lastName; } set { _lastName = value; } } public Customer Fill() { Customer customer = new Customer(); customer.FirstName = "Christoph"; customer.LastName = "De Baene"; return customer; } }

Inside your aspx page you have something like

Customer.aspx - Copy Code
<asp:ObjectDataSource id="customerDataSource" TypeName="IStaySharp.Business.Customer, IStaySharp.Business" DataObjectTypeName="IStaySharp.Business.Customer, IStaySharp.Business" SelectMethod="Fill" runat="server"> </asp:ObjectDataSource> <asp:ValidationSummary runat="server"/> <asp:DetailsView DataSourceID="customerDataSource" DefaultMode="Edit" AutoGenerateRows="false" runat="server"> <Fields> <rfx:BoundField HeaderText="Firstname" DataField="FirstName"/> <rfx:BoundField HeaderText="Lastname" DataField="LastName"/> </Fields> </asp:DetailsView>

Here is the result if you leave the properties empty:

Saturday, December 30, 2006 12:31:05 AM (Romance Standard Time, UTC+01:00)  #    Comments [10] -

 Sunday, December 24, 2006

That's what I call a christmas present. A CTP for Enterprise Library v3.0 has been released on CodePlex. More info can be found in this post.

Sunday, December 24, 2006 1:16:47 PM (Romance Standard Time, UTC+01:00)  #    Comments [0] -

 Monday, December 11, 2006
Version 0.23 of SyntaxColor4Writer is compiled against the new build release of Windows Live Writer 1.0.1 (Build 6) and Actipro Code Highlighter v4.0.0041.
Monday, December 11, 2006 12:55:38 AM (Romance Standard Time, UTC+01:00)  #    Comments [0] -

 Tuesday, November 28, 2006

Tom Hollander revealed some features/scenarios about the upcoming Validation Application Block that will be included in Enterprise Library v3. There are already some validation libraries available, for example

The fact that you can define rules through configuration is really cool. I can't wait for the CTP!

Tuesday, November 28, 2006 1:18:44 AM (Romance Standard Time, UTC+01:00)  #    Comments [1] -

 Monday, November 27, 2006

VISUG has a brand new website. All the necessary features are already available and more functionality is coming soon. The two last VISUG events for year 2006 are announced. One of the events is a panel discussion about exception handling and logging, and it will take place at Real Software (my home). The other event is a geek dinner where we can discuss about... you know what I mean ;).

Topic: Discussion on Enterprise Exception Handling and Logging

Description: This is a session where you (yes, you!) can discuss exception handling and logging in enterprise applications. Bring your tips and tricks, problems and exception handling frustrations with you, and we'll all learn about best practices together!
No slides or preparation required! Don't want to discuss? No problem, you're not required to say anything, but we hope you will. To help with a smooth discussion, it will be lead by a panel of 3 to 4 people. If you're interested to sit on this panel, you're invited (First-come, First-served basis).

When:
Monday 11 December, 18:30 - 20:30

Where:
Real Software (Prins Boudewijnlaan, 2550 Kontich, Route)

Register: VISUG website

See you on both events!

Monday, November 27, 2006 11:37:58 PM (Romance Standard Time, UTC+01:00)  #    Comments [1] -

 Wednesday, November 22, 2006

This macro enables you to nest project items inside Visual Studio .NET. Until now, there is no easy way to nest project items through the Visual Studio IDE, you can only do it by manipulating the project (.csproj or .vbproj) file and adding the DependentUpon element.

Inside the IStaySharp.vsmacros file there is a macro called 'Create Dependency' which allows you to nest two selected items. I have even created a video (672,18 KB) to illustrate how to configure and use the macro.

Wednesday, November 22, 2006 12:23:49 AM (Romance Standard Time, UTC+01:00)  #    Comments [30] -

 Sunday, November 19, 2006

I must have missed that one, but some weeks ago, version 3.0 of Windows Desktop Search for Windows XP/2003 has been released. If you need to search in netwerk files you can download Windows Desktop Search: Add-in for UNC/FAT. If you want to recognize more filetypes, check out the IFilters page on Channel9.

Sunday, November 19, 2006 1:41:50 AM (Romance Standard Time, UTC+01:00)  #    Comments [0] -

 Wednesday, November 15, 2006

PowerShell 1.0 has been released for Windows XP SP2 and Windows Server 2003. The bits can be downloaded here. If you already have installed a previous release of PowerShell, you need to uninstall by selecting 'Show Updates' in the 'Change or Remove Programs'.

Wednesday, November 15, 2006 12:39:07 AM (Romance Standard Time, UTC+01:00)  #    Comments [0] -

 Tuesday, November 14, 2006

One of the oldest and most basic programs is certainly the command prompt (cmd.exe). One thing is certain, you still can't do without the command prompt, and certainly being a developer.  I came across a nice tool, called Console, which enhances the command prompt. I have been using it for a couple of months now, and I really like it.

One of the things you should really customize is your PROMPT. More information about changing the PROMPT can be found here. Having, for example, your current directory path on a separate line is really useful. You can customize it through the environment variable called PROMPT, like Scott is doing, but I prefer passing it as a parameter to the cmd.exe. This way I can easily copy the application and no reboot is required. This can be done by the /k argument of the cmd.exe.

Here is a snippet of my XML configuration file for Console.

console.xml - Copy Code
<tab title="Console"> <console shell="cmd /k PROMPT $p$_$+$g" init_dir=""/> <cursor style="11" r="255" g="255" b="255"/> <background type="2" r="0" g="0" b="0"> <image file="" relative="0" extend="0" position="0"> <tint opacity="190" r="0" g="0" b="0"/> </image> </background> </tab> <tab title="cmd"> <console shell="cmd.exe /k PROMPT $p$_$+$g" init_dir=""/> <cursor style="11" r="255" g="255" b="255"/> <background type="0" r="0" g="0" b="0"> <image file="" relative="0" extend="0" position="0"> <tint opacity="0" r="0" g="0" b="0"/> </image> </background> </tab> <tab title="VS.NET 2005&