Jesse Johnston
.NET Dev. Good times with .NET and coffee

code2plan Filters

Monday, 30 March 2009 02:31 by jesse

Yesterday Denis and I released a new version of code2plan that includes a couple of long-awaited features: filter and search.

We've had filters for some time, but they weren't fully functional.  Our new release supports some great new filtering capabilities:

  • Filters are persistent.  You can save your filters by name, and they appear in the filters popup for the appropriate work items page.  A filter is always associated with a specific kind of work item, like tasks or stories.  The filter selected for a work items page is also remembered, so if you select the "Backlog" filter on the stories page, you'll still be looking at the backlog when you return to that page later.
  • Filters can be shared.  Just like work items, if you create a filter, all the other users in your team can see and use it.  Unlike work items, filters can also can be private, so you can have your own special set of filters that is visible only to you.
  • Filters can be organized.  For each work item type, there is a list of all filters.  You also have a list of favorite filters for each work item type that is specific to you.  You can add and remove filters to this list, and move filters up and down in the list.
  • Filters have new special values.  Almost all work item properties can be filtered on.  Most properties are standard types, like string, decimal, and date.  You can filter on specific values for these types (including "not set").  Date properties can also be compared to special values "today", "in the future", and "in the past".  These values are special because they are always evaluated at the moment the filter is run.  That means that your filter results will automatically change over time as existing date values move into the past.  Work item properties that refer to iterations can be compared to the special value "current iteration", which refers to whichever iteration is selected on the dashboard.  Finally, the owner property can be compared to the "logged in user", which refers to whoever is currently logged in.  All this means that it is easy to construct a filter like "my iteration tasks" which looks for tasks owned by the logged in user for the current iteration.  This filter will always be relevant regardless of who is logged in or which iteration is current.
  • Predefined filters.  We've included a bunch of filters out of the box to get you started.  These filters automatically populate the favorites list on each page.

Note that the Dashboard and Stories pages no longer implicitly filter on current iteration.  You'll see all tasks and stories unless you select a filter.  The iteration combo box on the Dashboard still sets the current iteration, but this is only used for the "current iteration" special value in filters, and for the burndown chart.

A browser-style search box has also been added to each page.  Here you can enter one or more words, which will be searched for in the work item name, description, and comments properties.  All of the words must be found for a work item to match, but they can be found in any of the properties mentioned.  On the people page, the search is performed on the login, first name, last name, and email properties.

Note that when a filter is applied, search will only return results that are also included in the filter.  So, if you have a filter selected for open defects only, a search won't return any closed defects.

There are a few other enhancements and bug fixes.  Denis spent some time revamping the color schemes for our users on Windows XP (you've reported that the colors weren't the best).  See the release notes for all the detail.

I hope you like the new version - go to www.code2plan.com and download it now.  code2plan is free!

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

code2plan Beta Release

Wednesday, 7 January 2009 16:48 by jesse

As a few of you might have seen, my side project code2plan is finally in beta.

code2plan is a free agile software project management application that is available as a Visual Studio 2008 add-in, and also as a standalone Windows desktop application.  Both versions have the same feature set, and both are WPF applications.  The program supports single users as well as supporting a shared database for teams.  You can work offline (no network connection required), and when you do sync up, a very straightforward conflict resolution feature helps you manage changes that you and other team members have made to the same data.

If you're an agile .NET developer, I would really appreciate your feedback on the program - both good and bad.  We'll be releasing new versions of the application very frequently, so there's a good chance that if code2plan doesn't work for you right now, it may very soon.  Just let me know.  Please post your comments to the forums on the code2plan web site so that everyone can benefit from the discussion.

I'll be posting here regularly over the coming weeks about the code2plan architecture, design thinking, and future plans.

Happy New Year!

Jesse

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Tags:  
Categories:   .NET | code2plan
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Using SQL Server 2008 Express as a default instance

Saturday, 13 September 2008 17:46 by jesse

Time to upgrade!  After uninstalling SQL Server 2005, I decided that I would try running only the Express version of SQL Server 2008 on my laptop.  After installing, I found that running SQLCMD against the (local) server no longer worked.  For example,

sqlcmd -s (local) -i SomeScript.sql

Resulted in this error:

HResult 0x2, Level 16, State 1
Named Pipes Provider: Could not open a connection to SQL Server [2].
Sqlcmd: Error: Microsoft SQL Server Native Client 10.0 : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online.
Sqlcmd: Error: Microsoft SQL Server Native Client 10.0 : Login timeout expired.

I had installed SQL Server 2008 Express as the default instance (and I don't have any other version of SQL Server on this machine), and accepted the default instance name SQLEXPRESS.

SQLCMD is connecting to the instance through named pipes, and the pipe name it connects on for the default instance is \\.\pipe\sql\query

To connect to a named instance, it connects through the named pipe \\.\pipe\MSSQL$<instancename>\sql\query

Sure enough, after opening Sql Server Configuration Manager, I expanded the Sql Server Network Configuration, double-clicked on Named Pipes, and was able to see that the pipe name included the instance name SQLEXPRESS.  After changing the pipe name to \\.\pipe\sql\query, my sqlcmd reference to (local) worked great.  Whew.

Named Pipes Properties

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Tags:  
Categories:   .NET
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | Comment RSSRSS comment feed

Architecture is important

Wednesday, 6 August 2008 16:17 by jesse

And not just in software!  But like design in buildings and furniture, software architecture is more than putting parts together so that everything works.  Software should be beautiful, classy and fun.  Ted Kamp and Mies Van Der Rohe obviously get that.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Moving My Blog

Saturday, 2 August 2008 10:45 by jesse

I changed my web hoster over the weekend, and when ran into a few snags migrating dasBlog to the new Windows Server 2008 / IIS7 environment.  While shoveling and wiring and taping, I found BlogEngine.NET.  Super cool.  It's a very simple and extensible .NET blogging platform.

To make a long story short, my blog is now running on BlogEngine.  I also changed the address to be a little easier on the eyes.  It's now www.teamjohnston.net/blogs/jesse (this is where you're at if you're reading this).  There's lots of new stuff coming soon...really.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

SQLCE Error 26100: The table name is not valid

Wednesday, 16 April 2008 00:05 by jesse

If you're using LINQ to SQL with SQLCE and use the DataContext.CreateDatabase() method, you may encounter this error.  If you used the LINQ to SQL class designer to generate the classes from a different database provider (such as SQL Server 2005 or SQL Server Express), the table source names may be prefixed with "dbo."

Just remove the prefix, and CreateDatabase() will succeed.

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:   LINQ
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

FatalExecutionEngineError returning from WPF PageFunction

Friday, 30 November 2007 01:17 by jesse

I'm posting this for future reference.  If you invoke a PageFunction and add an event handler to the PageFunction's Return event, the event handler must be an instance method of the calling page.  No other method will do.  If the event handler doesn't meet this criteria, you'll see the FatalExecutionEngineError thrown when you return from the PageFunction.  Sorry, no separation of concerns allowed.

More details in this forum thread: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1975763&SiteID=1.

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:   WPF
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

ClickOnce Error after upgrading to VS 2008

Thursday, 29 November 2007 22:04 by jesse

We recently upgraded to VS 2008 RTM at work, and shortly after discovered that a new build of our ClickOnce-deployed WinForms application failed to install correctly!  During the download process, a message box would display, and the log details revealed an InvalidDeploymentException (RefDefValidation) in System.Deployment.Application.DownloadManager.ProcessDownloadedFile().

Let me just say that days of fruitless investigation followed.

I'm happy to report that I finally did find the solution (completely by accident).  A new option has been added to Visual Studio, allowing you to automatically create and embed a manifest in your application.  This manifest allows you to provide proper application behavior when running under UAC in Vista.  Here's the option, on the Application property page of the Visual Studio project:Manifest Options

When you upgrade a WinForms project from VS2005 to VS2008, this option is automatically set for you.  If you had identified the application as a ClickOnce application in VS 2005, the resulting deployment from a VS2008 build works correctly.

Real-world ClickOnce

If you're like me, you're developing in a professional environment where you can't just click the Publish Now button and send an app from your development box into production.  Is it just me, or does everyone think that's insane?  Do you think we might want to QA those phasers first, Captain?

We have a relatively complex build that builds our ClickOnce manifests based on the target environment (Dev, QA, or Production) so that we can test ClickOnce updates from previous versions before going to production.  Also, since we've had our ClickOnce app deployed for more than one year, we had to overcome the certificate renewal problem, which requires a special signing process using both the expired and the current signing certificate.  Needless to say, neither of these can be set up in Visual Studio.  What we ended up with is a build where the ClickOnce options are not set in the Visual Studio project, but externally in an MSBuild project file, using many of the built-in targets that VS uses.

Migrating from VS2005

When the project was converted to VS2008, it was upgraded by the wizard as if it wasn't a ClickOnce project.  This means that the manifest setting was set incorrectly.

Here's what the Visual Studio documentation has to say about the manifest setting:

 

Manifest
Selects a manifest generation option when the application runs on Windows Vista under User Account Control (UAC). This option can have the following values:
  • Embed manifest with default settings. Supports the typical manner in which Visual Studio operates on Windows Vista, which is to embed security information in the application's executable file, specifying that requestedExecutionLevel be AsInvoker. This is the default option.
  • Create application without a manifest. This method is known as virtualization. Use this option for compatibility with earlier applications.
  • Properties\app.manifest. This option is required for applications deployed by ClickOnce or Registration-Free COM. If you publish an application by using ClickOnce deployment, Manifest is automatically set to this option.

The only options I see in the combo box are the first and second.  In our application, "Embed manifest with default settings" was selected by the conversion.  As soon as I chose "Create application without a manifest", I was able to build, deploy, and download with no trouble at all.

I still need to investigate the manifest issue further.  I want my users to have a great UAC experience with our app, and that means getting the manifest right.  For now though, "create without a manifest" is your quick fix.

Click On!

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Tags:  
Categories:   .NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Service Locator in Code?

Wednesday, 28 November 2007 03:04 by jesse

Phil Haack posed a question today about dependency injection frameworks:

Normally, I would just specify a type to instantiate as another PluginFamily entry. But what I really want to happen in this case is for StructureMap to call a method or delegate and use the value returned as the constructor argument.

...

Does anyone know if something like this is possible with any of the Dependency Injection frameworks out there? Whether via code or configuration?

I don't have much experience with the big three DI frameworks Castle Windsor, Spring.NET and StructureMap, but what I've seen suggests that these are strongly configuration based.

That means that I can specify a concrete type name in a configuration file that the framework will use to instantiate a particular interface type.  For example, in Spring.NET, you might specify the concrete type like this:

<objects xmlns="http://www.springframework.net">
    <object
        name="TheClassIWant"
        type="MyNamespace.MyConcreteClass, MyAssembly"
    </object>
</objects>

Then in your code, you can ask Spring to create an instance of MyConcreteClass like so:

IApplicationContext ctx = ContextRegistry.GetContext();
MyConcreteClass instance = (MyConcreteClass)ctx.GetObject("TheClassIWant");

That's all well and good.  In Phil's case, though, he wants to specify a way to create an instance of MyConcreteClass in code rather than configuration.  Let's take that requirement more generally and assert that we know what concrete classes we want to instantiate in our application, but just don't want the whole application to know.  Maybe I need an instance of ISomeInterface in some part of my code, but that code doesn't know how to get an ISomeInterface.  What I want is some global mechanism to define how to get an instance of some type, and then a way to get the type.  Now, how do we do that in code?

Simple Service Locator

I had some spare time while at DevConnections, and decided to create just that - a code-based service locator.  The basic idea is that we'll have a ServiceLocator class that maps interface types to concrete types.

At some point in your code, you register a concrete type for an interface:

ServiceLocator locator = new ServiceLocator();
locator.Register<ITest>(typeof(Test));

This means that when we ask for instance of the interface ITest, ServiceLocator will create and return an instance of Test (the implication of course is that Test implements ITest).  Here's how we ask for an ITest:

ITest instance = locator.Get<ITest>();

If you expose a singleton instance of ServiceLocator in your application, you can register your types at startup, and then use the locator to instantiate the concrete types from anywhere in the code.

What about parameterized constructors?

Default constructors are the trivial case.  How do we handle creation of concrete types that require constructor parameters?  We have two cases:

  1. The parameter is an interface that we want ServiceLocator to instantiate
  2. The parameter is a value that we want to provide explicitly.

Here's how we handle the first case:

locator.Register<ICat>(typeof(Cat), typeof(IOwner));
locator.Register<IOwner>(typeof(Owner));
 
ICat instance = locator.Get<ICat>();

Here we're saying that if we want an ICat, we need to create a Cat with the constructor Cat(IOwner).  By registering IOwner to create an Owner, ServiceLocator is able to create a Cat by first instantiating an Owner and passing that value to the Cat constructor.

In the second case, we have some value that ServiceLocator doesn't know how to create.  Let's suppose the Cat constructor takes an IOwner and a string:

locator.Register<IOwner>(typeof(Owner));
locator.Register<ICat>(typeof(Cat), new TypeParameter(typeof(IOwner)), new TypeParameter(typeof(string), "Kitty"));
ICat cat = locator.Get<ICat>();

In this case, ServiceLocator will call the constructor Cat(IOwner, string) with an IOwner it creates, and the string "Kitty".

And Singletons?

Sometimes we always want the same instance of an object:

Cat kitty = new Cat();
locator.Register<ICat>(kitty);
ICat cat = locator.Get<ICat>();

Here we always return the instance kitty when an ICat is requested.  We all know how hard it is to work with a large number of cats.

Le Delegate

Yes, there is a Santa Claus.  I might have some code that is responsible for creating an object.  Perhaps it's responsible for managing a pool of objects, or just has some complexity that would be difficult to express in configuration.  I want to register a delegate that will provide the instance.

locator.Register<ICat>(delegate() { return kitty.IsSleeping ? buffy : kitty; });
ICat cat = locator.Get<ICat>();

Here I provided an anonymous method in the Register() call, but I could just as easily register some other class method.

So there you have it - a configuration-free service locator with quite a bit of flexibility in object creation.

You can download the source for my ServiceLocator here.  The project was built in Visual Studio 2008.

Should I Use it?

If it works for you!  It's free of course.  However, I conjured this up in an hour or two, so it's not likely that ServiceLocator offers anywhere near the capabilities of a full-fledged dependency injection framework.  I'd encourage you to look closely at Castle Windsor, Spring.NET and StructureMap.  I'm sure that there are other great frameworks too.

I'd be grateful for any feedback as always.

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:   .NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Blog Action Day

Tuesday, 16 October 2007 00:09 by jesse

Today's entry is dedicated to environmental appreciation.

In the early ages of man, the earth was wild, cold, and full of danger.  We have waged war on the unruly forces of nature for thousands of years.  Compared to our savage upbringings, we live now in an unimaginable paradise of warmth, comfort and plenty.  A few isolated families scattered over a wide dark land now find themselves amongst a crowd of constant companionship and entertainments.  So far we have come.

We have laid low mountains, dammed rivers, harnessed the atom.  Nothing can withstand us.  Yet with our great advances, we've lost many of the empty spaces in our world.  Most is paved, groomed and domesticated.  So much so that few of us could live without civilization.  We could not feed or shelter ourselves, or find our way through a wild land.  Our very souls are tamed by the comfort and convenience of modern life.

That is why I value what wilderness and open spaces we have left.  Walking amongst the mountains and woods of nature is a breath-taking experience of the natural beauty and majesty of creation, so absent from our everyday modern reality.

2468It's an opportunity to recapture the simple joy of challenging ourselves against primal forces.  Hiking long distances, climbing, finding food, making fire and shelter.  Having to rely on your own problem-solving abilities and carry your own water.  Can we claim to be human without doing these things?

Every year I take my family on a pilgrimage to the woods.  Every time there are aches and pains, cold mornings, and often rain.  And yet it's always the best week of the year.

In the struggle against nature, we have defined ourselves.  Now that we are victorious, we have the luxury to choose how we relate to nature.  I'm grateful that we have chosen to preserve at least some of it, and hopeful that we will be good stewards to what is left of this crucible of humanity.  We have enough pavement.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | Comment RSSRSS comment feed