Comments, how-to's, examples, tools, techniques and other material regarding .NET and related technologies.
Saturday, November 14, 2009
C# 4.0: MethodBag, ExpandoObject and other cool stuff
Monday, November 09, 2009
IE8 and Selenium RC: Tests won't execute
Sunday, November 08, 2009
ASP.NET Forms Based Authentication: Minimum Configuration
<authentication mode="Forms"> </authentication> <authorization> <deny users="?"/> </authorization>Place this in your web.config file inside the system.web element. Of course it is likely that for production scenarios you will use something more sophisticated. However, for development purposes sometimes all you want is the minimum to get you started. And that's all the above is about.
Monday, November 02, 2009
ASP.NET, Master Pages and Selenium RC
[Test] public void MyTextBox() { _selenium.Open("http://localhost:49583/"); _selenium.Type("myTextBox", "some content"); // ... rest of the test }The problem with this is that the test will fail even if you have given your textbox the correct id. The reason for that is that ASP.NET mangles the identifier to something like "ctl00_..._myTextBox". You can't be sure how it is mangled next time when you compile the page or next time ASP.NET is update. The better approach is one that works regardless how the id is mangled so long as the original id is still included. So here we go:
[Test] public void MyTextBox() { _selenium.Open("http://localhost:49583/"); _selenium.Type("//input[contains(@name, 'myTextBox')]", "some content"); // ... rest of the test }Now of course you may need to locate an element more often so it makes sense to write a little method for this. With that method the test then becomes:
using csUnit; using Selenium; namespace MyWebSite.Web.Tests { [TestFixture] public class WebSiteTests { private string XPathForInput(string identifier) { return string.Format("//input[contains(@name, '{0}')]", identifier); } [Test] public void MyTextBox() { _selenium.Open("http://localhost:49583/"); _selenium.Type(XPathForInput("myTextBox"), "some content"); // ... rest of the test } // ... rest of the fixture private ISelenium _selenium; } }Although I found a few examples on the internet I thought that provide some concrete code might help you to get up to speed faster.
Sunday, November 01, 2009
WiX vs InstallShield
Saturday, October 31, 2009
Web user interface testing? Selenium!
- Create a folder for Selenium. I typically use c:\bin\selenium (I hate typing double quotes and stuff for command lines if folder names contain spaces)
- From the archive extract 'Selenium-Server-...' and 'Selenium-dotnet-client-driver-...' into the folder you create in step 1.
- Open a command prompt in the 'Selenium-Server-...' folder.
- Execute the command 'java -jar selenium-server.jar'
Saturday, September 05, 2009
Path used in Assembly.LoadFrom()
Sunday, August 30, 2009
AssemblyFileVersionAttribute and AssemblyVersionAttribute: A subtle difference
// Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]The issue that you may run in is that when you read the comment and infer that it applies to both AssemblyVersion and AssemblyFileVersion. That is not the case! AssemblyVersion can deal with wild cards as the generated comment suggests. For AssemblyFileVersion "wild cards are not supported". There is a solution however. If you simply remove the AssemblyFileVersion, the version will be picked up from AssemblyVersion. as the Win 32 file version. And for AssemblyVersion you can use wild cards. In that case your code in AssemblyInfo.cs would look like this:
[assembly: AssemblyVersion("1.0.*")] // No wild cards for AssemblyFileVersion! //[assembly: AssemblyFileVersion("1.0.0.0")] // Since AssemblyFileVersion is commented out AssemblyVersion // will be used for Win 32 file version.So the recommendation is: Comment out AssemblyFileVersion unless you can't get away without it.
Thursday, August 20, 2009
ReSharper 4.5 Plugin for csUnit
Sunday, August 16, 2009
Calling Process.Modules reliably
private static int GetModuleCount() { var currentProcess = Process.GetCurrentProcess(); try { return currentProcess.Modules.Count; } catch(Win32Exception) { // Wait until input message is empty and retry. currentProcess.WaitForInputIdle(); return currentProcess.Modules.Count; } }The first attempt assumes that the message loop is empty and the process in idle. If that call fails the code assumes that indeed more messages need to be processed so it waits until no further input needs to be processed. Then it simply tries again. If you need this method in several places in your code then you may also want to consider to create it as an extension method for class Process. I didn't implement the above code as an extension method since I needed it only in once place (hence it is a private method).
Friday, August 14, 2009
Some Tips for TeamCity
- Use a separate database server from the beginning. That way you save the database migration.
- When you migrate the database you execute a piece of Java code. You may have to specify a parameters for the JVM. Since the first attempts failed I had to tell the tool to clean out the target database first. To do this in the file migrateDB.bat locate the line that starts with "SET MIGRATION_JVM_OPTS". Add "-DforceClean=true" to the options. This will drop all tables in the target database. (You don't want to do that once you have migrated, so best is to remove this immediately after a successful migration!)
- In some cases the migration will fail and the error messages may not necessarily be a big help unless you have done migrations plenty of times. In my case I had a path to the old server configuration wrong. So check that as well.
- If the migration fails then check the log files. They provide good information.
- When specifying paths anywhere use forward slash instead of backslash, even on Microsoft platforms.
Sunday, August 09, 2009
Windows API Code Pack for .NET
Saturday, July 25, 2009
Problem using fuslogvw.exe
- This worked for me using the Windows SDK v6.0A on Vista. It may also work for other versions and other operating system versions but I didn't test that.
- The Fusion Log Viewer is also known as "Assembly Binding Log Viewer"
Monday, July 13, 2009
Silverlight 3 Tools for Visual Studio 2008
Friday, June 05, 2009
Background Color of TextBlock in Silverlight 2
<TextBlock ... Background="Red" ...> </TextBlock>Despite being correct Silverlight 2 doesn't like this XAML code. Trying to set it programmatically leads to an exception. Therefore a different solution is needed. Here is what works in my case. I use a Canvas and place a Rectangle and a TextBlock inside of that Canvas. Unless you set the ZIndex use this order so that the TextBlock is in front of the Rectangle. I use the Rectangle as the background for the TextBlock. When the TextBlock changes its size I update the size of the Rectangle accordingly. This solution is pretty simple in the end. First the XAML code:
<UserControl x:Class="Foo.LabelWithBackground" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200" Height="20"> <Canvas> <Rectangle Name="_labelBackground" Width="20" Height="20" Fill="LightSkyBlue"/></Rectangle> <StackPanel> <TextBlock Height="20" HorizontalAlignment="Left" Name="_label" VerticalAlignment="Center" Padding="4,2,4,0" Text="The Label Text" MinWidth="20"></TextBlock> </StackPanel> </Canvas> </UserControl>Next the C# code-behind:
public partial class LabelWithBackground : UserControl { public LabelWithBackground() { InitializeComponent(); _label.SizeChanged += LabelSizeChanged; } void LabelSizeChanged(object sender, SizeChangedEventArgs e) { _labelBackground.Width = _label.ActualWidth + _label.Padding.Left + _label.Padding.Right; } }Of course you can use this UserControl in either a page (Silverlight) or in a window (WPF). In both cases you will get a label with background.
Check out my blog on Agile Leadership
Thursday, June 04, 2009
WPF and Silverlight: Sharing User Controls
Check out my blog on Agile Leadership.
Friday, May 22, 2009
ReSharper 4.5 Memory Consumption
Just tried ReSharper on a fairly large solution with about 38 projects (13 C# and 25 C++). With the ReSharper addin enabled the memory consumption is sitting at about 1.5 GByte for the solution. With the ReSharper addin disabled the memory consumption is sitting at about 300 MByte for the solution. The solution itself has over 90% of its source code in C++ (mix of managed and unmanaged) and only a smaller portion in C#.
JetBrains claim they have worked on the memory consumption of ReSharper 4.5. Looks to me as if more work is needed ....
On my 32 bit box I have to reboot once in a while because I'm running out of memory when the addin is renabled ... (Vista 32 bit, VS 2008, 4 GB RAM)
Update on 04 June 09: It looks as if the memory consumption goes up to the same value with R# disabled. This happens when IntelliSense creates/updates its database. However, with R# disabled the memory drops back to normal once IntelliSense has finished that activity. With R# enabled it appears as if IntelliSense doesn't free up the memory. So it looks as if the problem is caused by the combination of the two. A solution with just C# project (and hence without IntelliSense in C++) doesn't seem to have that issue either.
Since I am in contact with JetBrains at the moment let's see what they can find based on the info I can provide.
Update on 02 February 2010: I had some conversations with JetBrains and they have asked me to provide an example that show the behavior. The challenge is that is seams to happen (or become apparent) only when there is a large number of C++ projects in the solution and the entire C++ code base is significant as well. While I do have an example to demonstrate the behavior, I’m a bit challenged to provide the very example. Would you send your entire code base? At the moment some members of my team have switched off ReSharper when they are working with the solution that also contains C++ projects.
Also check out my blog on Agile Leadership.
Monday, May 18, 2009
A comment on McAfee
- Wait until McAfee has finished scanning my system.
- Cancel the system scan so I can scan the downloaded file
Friday, May 15, 2009
I couldn't resist... - a quote from Subversion's web site
"all the memory we allocate will be cleaned up eventually" (Source: "Hacker's Guide To Subversion", retrieved 15 May 2009)I like that quote since I think it is true for all software! "Eventually" all memory will be cleaned up, and if necessary when the process terminates. On second thought, though, here might be an opportunity for a new business model! What if we had one-way memory? You can allocate it once, and once a process has consumed it you need to buy new DRAM (or maybe it could be called OW-DRAM as in "One Way"-DRAM). I'm sure Intel and other chips vendors would love it! But seriously (and I'm sure I've got some funny things somewhere in my published text and code as well. Tell me!): A memory leak is a memory leak is a memory leak. Using add and commit for adding large amounts of files consumes about 1 KByte per file. In one case I tried to add about 13,000 files and the process fell over when it reached 1.3 GByte having added only 10% of the files. So this approach doesn't work for version 1.6.1. All indications are that this is a memory leak. It is proportional to the number of files you add and try to commit. OS tools show how the process grows in size. It never shrinks (unless the process terminates one way or the other). Admittedly I didn't use a memory profiler, but what do you think the issue is when an error is reported on the command line saying "out of memory"? The better option for getting large sets of files into a repository - and that's what I learned by now - is to use SVN's import functionality. I have made several tests now with up to 65,000 files in one batch (several hundred MB) and the memory consumption of the client process grew only very slowly - from about 10 MB to 58 MB at most. This growth - I suspect - is probably related to memory fragmentation but definitely within acceptable limits. So the recommendation is: Don't use svn add and then svn commit. Instead use svn import if you have large sets of files to import. If they go into the wrong place you can always move them later using a repository browser such as the one that comes as part of TortoiseSVN.
Saturday, May 09, 2009
Handling of middle mouse click in Firefox 3.0
Friday, May 08, 2009
SVN Client: Out Of Memory
Sunday, April 26, 2009
ListView.GetItemAt() in WPF Application
private void _replacementsListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var mousePosition = e.GetPosition(_replacementsListView); var item = _replacementsListView.GetItemAt(mousePosition); if (item != null && item.Content != null) { EditTokenReplacement((TokenReplacement) item.Content); } }Since the WPF class ListView doesn't come with a built-in method I decided to implement an extension method as follows:
using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace Foo.Gui { internal static class Extensions { public static ListViewItem GetItemAt(this ListView listView, Point clientRelativePosition) { var hitTestResult = VisualTreeHelper.HitTest(listView, clientRelativePosition); var selectedItem = hitTestResult.VisualHit; while (selectedItem != null) { if (selectedItem is ListViewItem) { break; } selectedItem = VisualTreeHelper.GetParent(selectedItem); } return selectedItem != null ? ((ListViewItem) selectedItem) : null; } } }Please note that the position is passed into the method as an object of class Point. This means that the coordinates need to be relative to the list view object. In an event handler for a mouse button event, e.g. a double click, these can be calculated by using a method on MouseButtonEventArgs object that is passed into the mouse event handler. It's already shown in the first code snippet above but just to be on the safe side here are the relevant lines again:
private void _replacementsListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var mousePosition = e.GetPosition(_replacementsListView); // gets position relative to ListView var item = _replacementsListView.GetItemAt(mousePosition); ... }
Saturday, April 25, 2009
Getting Parent Window for UserControl in WPF
public partial class FooControl : UserControl { public FooControl() { InitializeComponent(); } private void _barButton_Click(object sender, RoutedEventArgs e) { var window = new MyWindow { WindowStartupLocation = WindowStartupLocation.CenterOwner, Owner = Window.GetWindow(this) }; if( window.ShowDialog() == true) { // Ok button clicked, do something useful here... } } }
Sunday, April 19, 2009
OpenFileDialog in .NET on Vista
using SWF = System.Windows.Forms; namespace FooApp.Presentation { internal class OpenFileDialog { public OpenFileDialog() { _dialog = new SWF.OpenFileDialog(); } public bool? ShowDialog(System.Windows.Window window) { return _dialog.ShowDialog(new WindowWrapper(window)) == SWF.DialogResult.OK; } public string DefaultExt { get { return _dialog.DefaultExt; } set { _dialog.DefaultExt = value; } } public string FileName { get { return _dialog.FileName; } set { _dialog.FileName = value; } } public string Filter { get { return _dialog.Filter; } set { _dialog.Filter = value; } } public string Title { get { return _dialog.Title; } set { _dialog.Title = value; } } private readonly SWF.OpenFileDialog _dialog; } }The only really interesting piece is the ShowDialog() method which takes a WPF window. System.Windows.Forms.DialogBox.ShowDialog() requires a IWin32Window instead (for easy access to the window handle), so we need a second wrapper class that looks as follows:
using System; using System.Windows; using System.Windows.Interop; namespace FooApp.Presentation { /// <summary>WindowWrapper is an IWin32Window wrapper around a WPF window. /// </summary> /// <remarks>Add System.Windows.Forms to the references of your project to /// use this class in a WPF application. You don't need this class in a /// Forms based application.</remarks> internal class WindowWrapper : System.Windows.Forms.IWin32Window { /// <summary> /// Construct a new wrapper taking a WPF window. /// </summary> /// <param name="window">The WPF window to wrap.</param> public WindowWrapper(Window window) { _hWnd = new WindowInteropHelper(window).Handle; } /// <summary>Gets the handle to the window represented by the implementer. /// </summary> /// <returns>A handle to the window represented by the implementer. /// </returns> public IntPtr Handle { get { return _hWnd; } } private readonly IntPtr _hWnd; } }With this machinery in place the client code in a WPF based application looks very familiar and simple:
var dialog = new OpenFileDialog { DefaultExt = ".dll", Filter = "Assemblies (*.dll; *.exe)|*.dll;*.exe", Title = "Select Assembly" }; if( dialog.ShowDialog(this) == true ) { // File is selected, do something useful... }As a result you have it all, simple client code, the correct OpenFileDialog on Vista and the dialog centered properly on its owner. The only thing that I still can't get my head around: After 8 years of .NET we still don't have a class available that is based on Window (or Form) and can be customized. It seems as if this is a puzzle that the guys in Redmond haven't figured out yet...
Wednesday, April 15, 2009
Separator for Menu Item in XAML (WPF, Silverlight)
<Menu ... <MenuItem ... <MenuItem ... <Separator /> <MenuItem> </MenuItem> </Menu>In C# use:
using System.Windows.Controls; Menu menu = new Menu(); ... menu.Items.Add(new Separator());
Tuesday, April 14, 2009
LinearGradientBrush with more than two GradientStop's in XAML
<lineargradientbrush key="WindowBackgroundBrush"
spreadmethod="Pad" endpoint="0.5,1" startpoint="0.5,0">
<gradientstop color="#FFFFDCDC" offset="0.56" />
<gradientstop color="#FFFF6F6F" offset="0.77" />
<gradientstop color="#FFFFDCDC" offset="1" />
</lineargradientbrush>
Monday, April 13, 2009
TextBox and other Controls with Transparent Background in XAML
- Set its Background property to 'Transparent'
- In Expression Blend select the Background brush and set the alpha channel to zero
Sunday, April 12, 2009
"The file 'x' is not part of the project or its 'Build Action' property is not set to 'Resource'"
The file 'x' is not part of the project or its 'Build Action' property is not set to 'Resource'It's not quite clear to me what causes this and it's not quite clear why Microsoft didn't fix it in Service Pack 1 for Visual Studio 2008 but here is a solution that may work for you:
- Add the file to your solution.
- Set its 'Build Action' to 'Resource' (in my case the drop-down also offers 'Embedded Resource' but that's not what you want)
- Select the image control.
- Set its Source property to the image file name. It should show up in the drop-down list. Next it may display the error message mentioned above. Then rename the image file to a short filename. Try setting the Source property of the Image control again. It should be fine now.
<Image ... source="Foo.Gui;component/pictures/myLogo.jpg" ... />The assumptions for this example are
- Your project is named 'Foo.Gui'
- That project contains a folder named pictures
- Your picture is in that folder and also included in the project. The name of the picture is 'myLogo.jpg'
Saturday, April 04, 2009
"Configuration system failed to initialize"
Friday, April 03, 2009
Membership Provider Implementation using NHibernate
Saturday, March 28, 2009
csUnit 2.6 Released
- csUnit is now based on .NET 3.5 SP 1
- Parameterized testing moved out of experimental
- Basic support for Microsoft unit testing.
- Several bug fixes.
- csUnit (no surprise!)
- NUnit 2.4.7 (.NET 2.0)
- Microsoft Unit Testing (basic support)
Friday, March 20, 2009
"Failed to create a service in configuration file"
- In the web.config file locate the XML node
within the node . For instance in the above example locate the node that describes the 'BarService'. Delete that node but leave in the file. - In the same file locate the node
with an attribute 'behaviorConfiguration' and an attribute value of 'BarService'. This node also contains the endpoints for the service. Remove this node. - Try again, and this time it should work.
Thursday, March 19, 2009
Updating Silverlight User Interface From Timer
// _statusMessage is a System.Windows.Controls.TextBlock object
// _statusMessageTime is a System.Threading.Timer object
private void DisplayStatusMessage(string message) {
_statusMessage.Text = message;
_statusMessageTimer = new Timer(ResetStatusMessageCallback,
/* params left out for brevity */);
}
private void ResetStatusMessageCallback(object stateInfo) {
_statusMessage.Text = "";
}
When the timer fires the callback is executed on a thread different to the user interface thread. The UI will not update. In my installation the Silverlight interface would then simply disappear! To fix this you need a way to execute the actual update on the user interface thread. One way is to use the Dispatcher object (Namespace: System.Windows.Threading) of the XAML page. Then the code of the callback implementation looks as follows: private void ResetStatusMessageCallback(object stateInfo) {
Dispatcher.BeginInvoke(() => {
_statusMessage.Text = "";
});
}
Another solution would be to use the DispatcherTimer. I spare you the details but you can check here for an example.
Monday, March 16, 2009
ClassInitialize Method Can Be 'static'
- TestClassAttribute
- TestMethodAttribute
- ExpectedExceptionAttribute
- ClassInitializeAttribute
Sunday, March 15, 2009
Implicit Typing Can Make TDD Harder
public class Result { public long Status { get; set; } } public class Foo { }Given this starting point you may want to write the following unit test to ensure that class Foo requires a method 'Result NewMethod()':
[TestMethod] public void TestNewMethod() { var foo = new Foo(); var result = foo.NewMethod(); Assert.AreEqual(0, result.Status); }As you type you will notice that when you have typed the dot after 'result' you will not be offered the member list of Result. It's not possible to implicitly type the variable 'result' since the method 'NewMethod()' doesn't exist yet. As a result writing tests in a TDD approach is slowed down when using 'var' instead of explicit types. Here is another view you may take: Writing tests for 'NewMethod()' should include all specifications, including the type of the return value. If you agree with that view you may want to avoid using 'var' in your unit tests. This certainly doesn't apply to people who create their unit tests after the method has been added to the class. I personally wouldn't call this test-first development, let alone test-driven development (or test-driven design as some people argue). Bottom line it depends on where you are coming from. 'var' might not always be the best choice even if it is a new 'cool' feature in C# 3.0.
Saturday, March 14, 2009
Passing Serialized Exceptions as Service Faults
using System.Runtime.Serialization; namespace AgileTraxx.Services { [DataContract] public class ServiceResult { public ServiceResult(string message, long incidentId) { Message = message; IncidentId = incidentId; } [DataMember] public string Message { get; set; } [DataMember] public long IncidentId { get; set; } } }This class would just take the incident id plus a message. The message could contain information about how to contact support and to note down the incident id. As you can see there is a lot to consider when designing a service interface, including security related factors.
Sunday, March 08, 2009
Service Reference for method returning void and out parameter
Thursday, March 05, 2009
Domain Objects with Validation in Fluent NHibernate
internal class WorkItem {
public WorkItem () {
}
public virtual long Id {
get {
return _id;
}
set {
_id = value;
}
}
public virtual string Title {
get {
return _title;
}
set {
_title = Validation.EnsureNonEmptyString(value, "Title");
}
}
private long _id;
private string _title = "";
}
I left most of it out. For now let's look at just the id and the title since those two demonstrate sufficiently the issue.
What you will notice is that the setter for the title contains validation code ("Validation.EnsureNonEmptyString(...)").
The problem starts when you query for one or more WorkItem's. Then NHibernate will use the property setters to initialize the instance of WorkItem. For strings the default value is null (nothing in VB.NET). With the given code, however, the validation will throw an exception since that is what it is designed to do. It doesn't care whether the setter is called by NHibernate or anything else.
So next I tried to figure out what alternatives I would have for validation and I found NHibernate.Validator. Although a step in the right direction I didn't like that the client code for the domain objects would have to explicitly call the validation. Alternatively the validation would have to be invoke via the event call backs from NHibernate. In both cases the domain class would only work properly if something else would collaborate. I didn't like that concept and started to look for an alternative.
And there is a quite simple solution to this: Change the configuration for NHibernate so that it doesn't use the properties to initialize the domain objects. This configuration change can be done via Fluent NHibernate as follows:
_hibernateConfig = new Configuration();
AutoPersistenceModel persistenceModel =
AutoPersistenceModel
.MapEntitiesFromAssemblyOf()
.Where(TypeIsIncluded)
.ForTypesThatDeriveFrom(
map => map
.DefaultAccess
.AsCamelCaseField(Prefix.Underscore));
persistenceModel.Configure(_hibernateConfig);
Depending on your naming conventions you may want to use a different access strategy or a different Prefix value. In my case it was Camel Casing with an underscore as a prefix.
After I finally found this solution I was able to keep the domain classes squeaky clean and at the same time stay with using the Fluent NHibernate interface and avoiding exception during the initialization of instances of domain classes.
Of course I'm not sure whether this is the only and/or best option. If you have other options that are even better, please drop me a note. I'm always keen to learn more!
Tuesday, March 03, 2009
Executing MS Unit Tests in csUnit
- TestClass
- TestMethod
- ExpectedException
Monday, March 02, 2009
Another Tool for Silverlight Unit Testing
Sunday, March 01, 2009
csUnit migrated to .NET 3.5 and VS 2008
Saturday, February 28, 2009
Designing Service Interfaces For Silverlight Clients
Saturday, February 14, 2009
Parser Error Message: Could not load type 'Global'
- Open the file containing your class Global typically located in the file Global.asax.cs,
- Note the namespace for that file
- Open the file Global.asax
- Locate the line that contains the element "... Application Codebehind=..."
- In that line ensure that the element "Inherits=..." includes the namespace for your Global class, e.g. MyWebSite.Global, (Inherits="MyWebSite.Global"). Replace MyWebSite with the namespace noted in step 2
- Recompile and redeploys.
- The error should be gone.