Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Wednesday, 15 December 2010

Enumeration-based property with initialiser fails to load in tool pane

I encountered what is likely an obscure issue today while using an existing enumeration to populate a drop down list in the tool pane of a SharePoint web part.

The web part didn't require a custom toolpart so I'm referring to a web part property defined within the web part class itself:

[SPWebCategoryName ("TWA")]
[FriendlyNameAttribute ("Region Override")]
[WebDescription ("Explicitly configure the region displayed when the mode is set to Region.")]
[Personalizable (PersonalizationScope.Shared, false)]
[WebBrowsable (true)]
public WARegions RegionOverride { get; set; }

Notice how the public RegionOverride property has a type of WARegions. Normally, the end result is an additional custom property displayed in the web part tool pane; in this case, the WARegions type is an enumeration and SharePoint therefore renders this as a drop down list:

Enumeration DDL

I say normally because today I was only getting a disabled DDL containing a single item ("Perth"). SharePoint was also kind enough to present me with this vaguely useful error message:

Some of the properties for this Web Part cannot be displayed properly. For more information, see your site administrator.

The WARegions enumeration is an existing enum I chose to reuse for the sake of convenience. Upon further inspection, I noticed the first element in the enum (Perth) was explicitly assigned a value of 1. Acting on my suspicion, I removed the explicit assignment and the DDL would then display as expected.

As a final test to confirm whether the explicit initialisation was somehow behind the single list item being displayed, I set default values for all elements in the enum but the error returned. Fortunately in my case I can do away with the explicit initialisation (which I'm not keen on—I prefer to initialise enums myself).

If you found this post helpful, please support my advertisers.

Thursday, 18 November 2010

DateTime format safe for file system

Couldn't find anything similar when I searched so thought I'd throw this out there for use in file names in a Windows file system:

DateTime.Now.ToString ("yyyyMMddHHmmss")

Will output "201001312359"

Add a ".txt" or ".dat" if you're hard-core and you're all set.

If you found this post helpful, please support my advertisers.

Sunday, 11 July 2010

C# Object Initialisers and trailing commas

C# 3.0 (.NET 3.5) introduced some really handy new features and hidden gems—and I'm still coming across the latter today.

If you've been developing with C# 3.0 for a while, you'll know about object and collection initialisers: they allow you to initialise the members of an object or a collection at instantiation-time, rather than having to declare a variable and then assign values to the members of that variable. It's a convenience thing and makes life easier in a LINQ context (although the debugging experience in VS2008 sucks).

When looking back through a piece of code I written previously, I noticed I'd inadvertently left a trailing comma after the final assignment in the list. I thought this was unusual because the code compiled and the C# is normally anything but lazy when it comes to most language constructs.

StaffMember staffMember = new StaffMember()
{
    FirstName = "Michael",
    Surname = "Hanes",
};

Sure enough, the ECMA C# Language Specification actually notes the following in the section about Array Initializers: "[…] C# allows a trailing comma at the end of an array-initializer. This syntax provides flexibility in adding or deleting members from such a list […]" (page 363, section 19.7). Interestingly, object and collection initialisers simply inherit this behaviour and the ability to initialise both arrays and enums in this way is not C# 3.0-specific (the specification document actually cites the C language).

In my opinion this is a rational design decision that increases the useability of the C# language by developers. By contrast, I'm forever having to shift SQL select statement commas around when commenting out individual lines and it's a major inconvenience. Development is normally a very fluid, experimental time in the lifecycle of a code artefact and anything that simplifies that exercise and increases maintainability is a good thing.

Tuesday, 16 March 2010

C# var recommendations

With a recent move to .NET 3.5 we’re beginning to review our coding standard and consider some of the things C# 3.0 makes available to new and experienced developers alike. One of these things is the contentious var keyword.

‘var’ seems to instil fear into some developers with others viewing it as total awesomeness. Like all things, var has its place for storing anonymously typed objects returned from the likes of a LINQ query but can it really be misused?

While var does at first glance appear to be a merger of JavaScript and VB with C#, it’s important to note the use of the var keyword must comply with the following:

  • A variable declared using the var keyword must be initialised within the same statement
  • An object with a different type cannot be assigned in a subsequent statement
  • Variables declared with a type of ‘var’ are strongly-typed and compile-time checked; instead of having to determine the type yourself, the compiler does it for you
  • Intellisense will continue to work wherever the variable is used
  • The var keyword can only be used for local variables within a method

Commenters responding to a blog post by Steven Wellens on the use of the var keyword also cited an improved refactoring experience; I partially agree with this point however Visual Studio’s refactoring tools largely take care of those problems.

The main reasoning by commenters was for (and against) readability and I agree strongly that using var reduces “noise” words in the code. In my view, this improves the ability to easily scan the code.

The example statement Steven supplied was claimed to be unreadable—but primarily for the poor name chosen for the GetData method:

var data = GetData();

If the method is renamed, this does remain a gray area unless it also includes type information in the name, which is yucky. Removing type information does allow intent to shine through of course—not a bad thing.

With this preface, here are the draft recommendations for use of the var keyword in our shop:

  • Do declare the type if it's useful otherwise use 'var' to avoid "noise" where type information is unimportant or can be read in the object's initialisation. Eg: var cat = new Cat ();
  • Do use 'var' to highlight intent over implementation detail
  • Do use 'var' as required for anonymous types
  • Consider readability; avoid examples like var data = GetData(); where the type returned by GetData() is not obvious

References

Monday, 15 March 2010

How to return an anonymous type from a method

Current .NET lore would have you believe you can’t return an anonymous type from a method but Tomas confirms it is possible by casting and cites the C# 3.0 spec:

Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and types in the same order will produce instances of the same anonymous type.

Tomas also qualifies his interesting post with a request to let him know if a good reason can be found for using this technique!

In my own work I recently wanted to call a method that returns what I would ultimately implement as a data transfer object: a strongly-typed collection of structured, related data. I considered out parameters and collections but neither option really struck my fancy; a DTO would likely be the preferred option at the expense of introducing another class, maintenance overheads, etc.

In the hunt for a better, modern solution, the concept of returning an anonymous type appealed—apart from the problems anonymity introduces! While I understand how .NET constructs anonymous types and reuses those that identical, the one major problem I see with Tomas’ solution is the requirement that both “sender” and “receiver” not only know about the so-called anonymous type but actually define it in two places. This just seems like more overhead to me so I abandoned this approach before long.

Wednesday, 16 December 2009

Inner exception details displayed instead of wrapper exception

Wrapping an exception using the Exception (string, Exception) constructor and throwing the new exception in place of the original isn’t behaving as expected for me today: ASP.NET 3.5 displays the inner exception message in its default exception display; I expected to see the wrapper exception message. Oddly enough, details pertaining to the wrapper are logged to the Application event log.

So this:

try {
// Setup to make something go wrong
throw new Exception ("Inner exception");
}
catch (Exception ex)
{
// Wrap the inner exception and throw
// a new exception instead
throw new Exception ("wrapper exception", ex);
}

spits out this (note both the message and source error clearly pointing at the inner exception line):

Inner exception

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Exception: Inner exception

Source Error:

Line 18: try
Line 19: {
Line 20: throw new Exception ("Inner exception");
Line 21: }
Line 22: catch (Exception ex)

Despite what the message and highlighted code reveal, the stack trace does imply the wrapper exception was involved along the way.

[Exception: Inner exception]
_Default.Page_Load(Object sender, EventArgs e) in Default.aspx.cs:20

[Exception: wrapper exception]
_Default.Page_Load(Object sender, EventArgs e) in Default.aspx.cs:24 …

Adding a second try/catch to catch any exception of type Exception and inspecting the results locates the inner exception property where I’d expect it to be. Alternatively, “swallowing” the inner exception in the original catch block and throwing a new exception using the Exception (string) constructor does just that—no sign of the inner exception. I’ve additionally tried catching different types of exception (I was originally throwing ApplicationExceptions and catch Exceptions) and constructing my own exception classes with the same effect.

Maybe I’m missing something but this seems like pretty basic stuff and a few other vaguely related search results hint that I’m not alone with this one. Of course, I can always handle all exceptions myself to prevent anything killing the application but the current approach is convenient at the moment for debugging outside production where it’s less convenient to attach a debugger or check the event logs.

If you’ve got any ideas or have come across this yourself, I’d love to hear your thoughts!

Friday, 31 July 2009

Storing SharePoint List meta data

When I recently wanted to store some information about a list (i.e., meta data) I couldn’t find an obvious way using just SPList. SPList does expose the PropertiesXml property but doesn’t expose a setter. What I wanted was a property bag or hashtable of key/value pairs. I’ve seen suggestions to add an extra column for this purpose but that could lead to redundant data, extra maintenance, and wasted space and essentially becomes meta data about the list items. In my opinion, columns define the structure of the data and aren’t meta data (but feel free to debate that among yourselves!).

Alex Angas was kind enough to provide an answer to a question I posted on StackOverflow on this subject. His solution was to make use of the Properties hashtable hanging off the list’s RootFolder object (SPFolder) and here’s my code to do just that:

// Set the custom property
SPList myList = myWeb.Lists [“MyList”];

myList.RootFolder.Properties [“MyKey”] = “MyValue”;
myList.RootFolder.Update ();

// Retrieve the custom property
myList = myWeb.Lists [“MyList”];

string myValue = myList.RootFolder.Properties [“MyKey”] as string;

Nice. It’s worth pointing out that using SharePoint Manager 2007 the RootFolder can be found within the site collection root; expand the RootFolder node to locate the folder named after the list in question.

SPFolder RootFolder Properties

Update: Although RootFolder.Properties is a System.Collections.Hashtable, you’ll likely receive a SPInvalidPropertyException if you attempt to use anything other than a string, int, or DateTime. The debugger told me so ;-)

In answer to the same question Paul-Jan also suggested using a separate, hidden list to track meta data about a parent list (or lists, I suppose). I quite like this idea as a centralised “list meta list” and it could be as simple as three column list to identify a list by ID and store a key/value pair. On the other hand, I prefer keeping stuff like meta data with the object in question so my preference would be SPList.Properties; the RootFolder solution seems like a passable alternative.

Thursday, 7 May 2009

Collapsing multiple using statements

Multiple, nested using statements are extremely common when developing against the SharePoint API to ensure the various objects at work are disposed of correctly:

using (SPSite site = new SPSite ("http://server")){
using (SPWeb web = site.OpenWeb())
{
str = web.Title;
}
}

Under the hood, the CLR transforms both using statements into two try/finally blocks—one nested inside the other—where the relevant object is disposed in each finally block. Handy but these multiple using blocks still leave the code that does all the real work of your application indented far into the page. Add some if statements, loops, or RunWithElevatedPrivileges calls and you’re halfway across.

To clean up ever so slightly, the two using blocks in the example above can actually be combined or stacked with a single block (a single set of braces and a single level of indentation):

using (SPSite site = new SPSite ("http://server"))
using (SPWeb web = site.OpenWeb())
{
str = web.Title;
}

The end result is the same at the MSIL level: two try/finally blocks nested one inside the other (check ildlasm.exe) but you regain one level of indentation.

System.Random not so random in a loop

When you need to generate a random number System.Random comes to mind:

int randomNumber = new Random ().Next ();

All well and good but did you know new Random () actually generates a sequence of random numbers and Next () simply returns the next random number in the sequence? The Random class could have been named more accurately as RandomSequence but I digress…. One more thing, did you know the random sequence is generated using a seed value and that if you specify the same seed value when constructing a new Random object you’ll get the same sequence of random numbers? And finally: did you know if you don’t specify a seed value, the seed value is initialised using the system clock which naturally “has finite resolution.”

If you answered no to all of the above and you need a random number go read the doco. If you’re an attentive reader, you’ll read this:

…using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.

Which sucks because that’s exactly what happens if you use the above code in a loop on a machine that can execute that loop more than once before the clock ticks over. If that happens, the same seed value will be use and calling Next () on the new Random object will return the same value it did last time.

The easiest way to work around this is to instantiate your Random object outside the loop and then call Next () on that instance in the body of the loop:

Random randomSequence = new Random ();

for (int i = 0; i < 10; i++)
{
randomSequence.Next ();
}

If that doesn't suit, consider passing the Random constructor a seed value that increments with each iteration of the loop (the MSDN documentation suggests there may be performance implications if you create a new Random object repeatedly so watch out).

For what it’s worth, today we were dealing with this exact problem in the context of an anonymous method passed to the List<T>.Sort () delegate. The IComparer<T>.Compare () method supplied to Sort () only accepts two parameters (those to be compared).

int Compare( T x, T y)

As a developer, it’s easy to assume the anonymous method only has access to its parameters. In actual fact, variables in the “outer scope” are captured and made available to the delegate until the delegate referencing the anonymous method itself goes out of scope and become eligible for garbage collection:

The local variables and parameters whose scope contain an anonymous method declaration are called outer or captured variables of the anonymous method.

Read more about closures if you're interested...

What this means is that our anonymous method can access the Random instance declared in the outer scope:

Random randomSequence = new Random ();

list.Sort
(
delegate (string x, string y)
{
return x == y ? 0 : randomSequence.Next (-1, 1);
}
);

There’s some extra stuff going on here because the result returned must conform to the IComparer<T> interface in that it must return –1, 0, or 1 but the code in bold calls out the use of the outer variable within the anonymous method.

Saturday, 31 January 2009

Disposing SharePoint Services Objects Updated (2009) and SharePoint Dispose Checker

Microsoft has finally released an update to the "Best Practices: Using Disposable Windows SharePoint Services Objects" article. If you've never heard about, glanced through, or read this article, it's required reading for every WSS/MOSS developer and worth printing off.

It's terribly important to remember that, even though you're writing code for a managed environment (.NET), you're not always dealing with managed objects; think of your MOSS objects (well, some of them anyway) as unmanaged resources that require special handling just like files and database connections. If you don't dispose of these objects properly, they'll sit in memory until the IIS application pool falls over and your site crashes. It happens and the existence of this article suggests it happens too much! The flip side is disposing of MOSS objects that shouldn't be disposed, which can also have negative consequences.

To coincide with this guidance, the SharePoint Dispose Checker tool (SPDisposeCheck) has also been released on the MSDN Code Gallery. Pointing this tool at your custom MOSS assemblies will tell you where you've gone wrong. The tool won't find every problem and may also report errors which are not actually problems but in general it's a great addition to your toolbox and a perfect compliment to the guidance. The tool can be used with MOSS or WSS assemblies. Note the -xml parameter doesn't work with this release--leave it off the call and pipe the output to a txt file. 

The tool is installed to "C:\Program Files\Microsoft\SharePoint Dispose Check" and running against the sample spits out a list of problems that look something like this:
ID: SPDisposeCheckID_160
Module: SPDisposeExamples.exe
Method: SPDisposeExamples.SPWebLeak.SPLimitedWebPartManagerLeak
Statement: webPartManager := page.{Microsoft.SharePoint.SPFile}GetLimitedWebPartManager(1)
Source: C:\ROGERLA\Demo\SPDisposeExamples\SPWebLeak.cs
Line: 42
Notes: Dispose/Close was not called on SPLimitedWebPartManager.Web
More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_160
Interpreting the SPDisposeCheck's output isn't difficult but note the tool may output a lot of information before telling you about the problems encountered. Scanning the westernaustralia.com .dlls resulted in a 10MB text file to report three problems so I'd suggest you start reading the output file from the bottom up or run the tool without the -debug parameter. Also make sure you read the readme file as it's not only quite useful but brief.

Finally, despite being labelled "Best Practice", this guidance has danced around since it was first published in 2006. But don't worry, Roger Lamb keeps and excellent, up-to-date
blog post on how to implement this guidance and any changes that come up. Apparently Roger's blog will be the default location where updates are published prior to incorporation into the doc proper. 


Custom-Built Microsoft Office SharePoint Server 2007 Branded Sites and Webpart Development - info@mediawole.com

Thursday, 3 January 2008

C# Switch Fallthrough with goto

Everyone hates the thought of goto because it was so well abused back in the day. I've seen so many coding standards denying the use of the goto keyword due to the risk of introducing "spaghetti code". So let's make things very clear: I am not advocating the use of goto as a general control flow mechanism except in the very few cases where it's warranted. In other words, don't assume I'm a freak of nature simply because I've even mentioned goto in a positive light and it's not 1968.

As you're no doubt aware, C# is a modern programming language following in the tradition of C, C++, and JAVA. It's full of all the standard control flow operations like for, foreach, while, do...while, if, and switch and it also attempts to remove a number of trouble spots available with its ancestors (automatic fallthrough in switch statements, pointers, memory cleanup). So one must ask, then, why the language retains the lowly goto keyword! I've read examples of using goto in languages that don't support modern control flow constructs; in that context it makes perfect sense to overcome a deficiency of the programming language using the fundamentals provided. So how does it fit in today?

The behaviour of the switch statement in C# may not be what you're expecting if you're coming from a C background because case blocks don't "fall through" by excluding a break statement. Every C# case block must contain a break statement. This is a good thing because if you inadvertently forget a break statement in a language like C, the compiler may not warn you about the omission and case blocks will continue to execute until the switch statement ends or a break statement is reached. The end result: a defect--and potentially a very significant defect. In C# if you omit the break statement compilation will fail.

At first glance this sounds like the C# language doesn't allow fallthrough in a switch statement but that's only partly true: C# doesn't allow automatic fallthrough in a switch statement. If your design requires a case block fall through you can enable this behaviour explicitly using a goto statement. If you control yourself and don't run out and replace all of your existing control flow statements with gotos, you can even use a goto without feeling dirty all over.

I lied above when I said every C# case block must contain a break statement because you can optionally replace the break statement with a goto statement. If you write your goto statement to go to the next case statement, you achieve falthrough. Moreover, if your case statements are later reordered, your gotos will preserve the original fallthrough ordering unless the gotos are also updated--a bit of a pain but worth the extra safety.

Here are two examples switching on ints and strings:

switch (1)
{
case 1:
Console.WriteLine ("case 1");
goto case 2;
case 2:
Console.WriteLine ("case 2");
break;
default:
break;
}

switch ("hello")
{
case "hello":
Console.WriteLine ("case hello");
goto case "world";
case "world":
Console.WriteLine ("case world");
break;
default:
break;
}


Wednesday, 2 January 2008

Accelerated C# 2008 by Trey Nash (Apress)

An aside about this review...

I volunteered when an email from Apress asking for “fresh voices to write about [their] recently published, hot-off-the-press .NET 3.5 titles” was circulated to the members of the Perth .NET Community of Practice late in 2007. In return for reading two electronic books and posting a review of each to the Amazon, Barnes & Noble, and bookpool sites, Apress promised to supply reviewers with the printed versions and an additional ebook. Apart from the freebie, I thought this would be a great opportunity to freshen up my skills and interact with a significant technical publisher. Apress withdrew their offer of the free printed books due to a large response but I’ve got to say this was nonetheless a very cool offer on their part.

That said, I must make two key points:
  • My review is entirely unbiased and the free offer was by no means inducement to write a positive review. My favourite titles to date have originated from Microsoft Press, Addison-Wesley, and Wrox and I hate nothing more than wasting my time with a weak book from a publisher that pays little attention to detail.
  • I don’t write books about Information Technology and I don’t produce the technology to support the software production process; apart from an undergraduate English Literature degree, a master’s IT degree, and four very intense years on the ground, I’m not an authority on anything, let alone C# and .NET 3.5.

This is the first review of two. The second review will be for Pro C# 2008 and the .NET 3.5 Platform, Fourth Edition and will follow soon (I’m a slow reader).



Accelerated C# 2008 is one of those books you stumble across every so often that answers so many questions you know it will reside on your bookshelf for some time to come. Trey Nash offers an in-depth look at C# 2.0 and 3.0 without the excess material most experienced developers are already familiar with. Although the book is strongly focussed on C#, many of the concepts discussed can also be extracted out and filed under the broader titles of object oriented development and software design. Bringing together a book spanning many of the changes and new features from .NET 1.1, 2.0, 3.0, and 3.5 is a big ask and despite a few minor issues I’d recommend every developer working with C# 2.0 and on read this book.

The book is a mere 510 pages but in my mind that makes a text like this all the better. Nash’s writing style is to the point and meticulous, skimming over concepts with which most experienced developers should already be familiar in early chapters (“this is a book for experienced object-oriented developers”) and diving in to cover some of the great features introduced with C# 2.0 and 3.0 at close range. After years of reading about the superficial aspects of boxing and learning about generics and iterators first hand, for example, I finally understand the underlying mechanics of these issues that simply aren’t covered in the MSDN documentation and high-level technical articles. More importantly, I now feel I have the knowledge to discuss these concepts and put together truly effective designs from the information acquired from this book.

As a fairly advanced, special-topic book, I wouldn’t classify this as an academic text but the author discusses each topic in a fairly “textual” manner. In other words, there is a strong focus on how the C# language embodies specific concepts before delving into the practicalities and code samples. Individual subjects are examined in detail but are also related to the CLR, object oriented and functional programming concepts, best practices, and coding efficiency. This is personally my preferred format but I wonder if it will appeal to a broader audience.

My favourite chapters include the rather lengthy chapter four (“Classes, Structs, and Objects”), chapter eleven (“Generics”), and chapter thirteen (“In Search of C# Canonical Forms”). Chapter thirteen in particular was a great starting point for defining key considerations when designing types in C# and despite its length, I think this chapter could have gone further.
The title of Accelerated C# 2008 sounds to me like a marketing title. I say this because

a) there’s no such thing as C# 2008. There’s C# 3.0 and Visual Studio 2008 but they’re not the same thing; and more importantly

b) while most chapters in the book apply to C# 3.0, all but the final three chapters describe features specified with C# 2.0 and shipped .NET 2.0/Visual Studio 2005.

The first point is just me being nitpicky. The second point stems from a nagging feeling I had while reading this book that it was originally written as Accelerated C# 2005 and jazzed up at the last moment to reflect the changes and improvement brought about by C# 3.0. The structure of the book reflects this assumption as only the last three chapters relate specifically to C# 3.0. If you currently work with C# 2.0 day to day you won’t go wrong with this book—it’s filled with many insights and gems that can only be learned by experience or taught by a great teacher (eg. Nash); as a C# 3.0 book, however, I think there’s room for improvement. To illustrate this gripe, the author frequently indicates many of the language features new to C# 3.0 are there to support LINQ but the final chapter in the book (“LINQ: Language Integrated Query”) barely scratches the surface. Other resources are referenced but this is one subject that should have been examined at greater length at the cost of some detail.

It would have also been helpful to have the various code samples in each section align better with each other. There’s nothing more frustrating than reading about employees in the context of one topic and Bluetooth radios in the next. I think the IT publishers as a whole need to do better at this. I also would have liked to see a few more guiding comments in the code samples covering trickier aspects of the code. Overall, however, the code samples are well formatted and concise and illustrate the discussion very well.

The book in general is formatted and organised very well and despite the heavier material it contains, the book is a pleasant read. The chapter summaries seem to follow the old presentation approach of tell ‘em what you’re gonna tell ‘em, tell ‘em, and then tell ‘em what you told ‘em; as a result, each chapter summary quickly rehashes the chapter content at a very high level where it would be preferable to have a decent summary that makes theses bits worth reading. As Nash is obviously a well read individual, I was also really hoping for an annotated bibliography.

Overall, I loved this book. It was a great refresher on some of the aspects of C# 2.0 I deal with less frequently and tend to forget about, a thorough insight into what it means to think like a really, really good developer, and a good introduction to C# 3.0. I’m looking forward to the next edition when C# 3.0 has matured and the author has some really C# 3.0-specific insights to convey.

Sunday, 16 December 2007

Senior Developer Interview Questions

We had a couple of senior developer tenders go out at work recently and when it came time to interview the applicants I was asked to put together a test to flush out the wannabes. I've been on the receiving end of these tests in the past and considering this test would be written in the twenty to thirty minutes before a three-panellist interview, I thought I wouldn't be too hard. I'd say most of these questions are analyst programmer questions, if not junior dev questions, although I did through in a few tricks to gauge experience and I also left some questions fairly open in an attempt to understand the applicant's though process. If the applicant couldn't complete the test in the time period given, that would be okay too.

I've included the job criteria headers to help you figure out what I was looking for in each answer; not every question fits within a specific heading. The headings were printed on the test sheet.

The Perth .NET developer market has been on fire since I arrived two years ago and SharePoint work is going through the roof; as a result, we only had a single applicant put forward for the two or three tenders that went out. When and if we have more people across this test I'll attempt to generalise the results and post an update to this post on the effectiveness of this test.

I haven't included the answer here because like I said, some of them are fairly open and a lot of them should be fairly obvious if you've done an undergraduate CS course.

At least 5 year of software development experience and at least 2 year experience developing MS .NET applications

  1. Describe the difference between the execution environments for C++, C#, and Javascript
  2. Is C# a weakly-typed language? Why or why not?
  3. When should performance optimisation occur?
  4. List three problems with this code. Bonus: how could it be improved if you were using .NET 3.5?

    private string someVar = 1234;

    public string SomeVar
    {
    get
    {
    if (string.IsNullOrEmpty (someVar))
    {
    someVar = “5678”;
    }

    return SomeVar;
    }
    set
    {
    someVar = val;
    }
    }

  5. When would you mark a class with the internal visibility modifier?
  6. What’s the difference between a struct and a class? Are structs allocated on the heap?
  7. The property invocation below may return a null result. Rewrite the code to prevent the second line from throwing.

    object result = Employee.Address;
    result.ToString ();

Working knowledge of full lifecycle development methodologies, process and standards and project management; sound knowledge of object oriented system design and development...

  1. List one section heading you might expect to find in each of the following documents:

    · A functional specification
    · A technical specification
    · A UAT test case
  2. List three tasks you would complete before checking in a new class to the Tourism WA source control system.Name each component in the following diagram and briefly explain the relationship between Vehicle and Door:
  3. What is a use case?
  4. Briefly describe the difference between a class, an interface, and a type
  5. Briefly describe a software design pattern you’ve used on a past project and indicate how it helped or hindered code maintenance. Alternatively, describe a design pattern employed by ASP.NET.
  6. After designing a new system, your project manager asks you to estimate construction time for yourself and a junior developer. This is the first time the department has built this type of system and you haven’t previously worked with the junior developer. List three techniques you would consider to ensure your estimate is as accurate as possible

Solid understanding of internet protocols, web development mark-up languages and web standards...

  1. Draw a simple diagram showing the location of a reverse proxy in relation to a database server, a web server, the internet, and a client
  2. Using only inline CSS and DIV tags, write the HTML to produce a three-column, one row table (don’t worry about borders). Don't use tables.
  3. Will the Hello World! text be rendered green, red, or blue by the browser?

    &lt;style>
    span { color: green }
    #makeItRed { color: red; }
    .makeItBlue { color: blue; }
    &lt;/style>
    &lt;span id="makeItRed" class="makeItBlue">Hello World!&lt;/span>
  4. List three key components of this schema fragment. How many ReservationRequest elements are allowed in an XML document validated against this schema?

&lt;xs:element name="Control">
&lt;xs:complexType>
&lt;xs:sequence>
&lt;xs:element name="ControlID" type="xs:int" minOccurs="0" />
&lt;xs:sequence minOccurs="0">
&lt;xs:element name="ReservationRequest">
&lt;xs:complexType>
&lt;xs:sequence>
&lt;xs:element name="InDate" type="xs:dateTime" />
&lt;xs:element name="Period" type="xs:int" />
&lt;xs:element name="Adults" type="xs:int" />
&lt;xs:element name="Children" type="xs:int" />
&lt;xs:element name="Infants" type="xs:int" /> &lt;/xs:sequence>
&lt;/xs:complexType>
&lt;/xs:element>
&lt;/xs:sequence>
&lt;/xs:sequence>
&lt;/xs:complexType>
&lt;/xs:element>

Sound knowledge of the Microsoft .NET framework class libraries, ASP.NET and Web Services

  1. What improvements does the .NET 2.0 System.Collections.Generic namespace offer over the System.Collections namespace from previous versions of the framework?
  2. List two key differences between a user control and a web control
  3. Compare the .NET application cache and the ASP.NET output cache
  4. Write a call to the Format ( ) method of the String class to return the string “Sam is 38 years old.” Assume you have a variable declared and initialised as follows:

    int age = 38;

    Give an example of a situation when you would use a StringBuilder instead

  5. Describe the difference between application state, session state, and view state. Discuss session state in relation to scalability and suggest an alternative.
  6. List two techniques to secure web service communication on the internet

Ability to perform unit and integration testing...

  1. What purpose do the following serve when debugging a section of code:

    · The F11 key on your keyboard
    · The Immediate window

  2. Briefly describe the concept of “regression testing”
 

Copying a SharePoint Document Library Programmatically

Based on the number of posts out there about copying the content of a list or document library, I'm willing to suggest SharePoint hasn't made this particular task easy. Whether it's through the various UIs or programmatically, this task seems like it's more difficult than it should be. As I recently found out, even clearing the content in an existing list is a hassle.

Before I go on, a bit of background. We were initially using the in-built variation tools to copy content from a source language site to a number of target English sites--in other words, www.westernaustralia.com/en was being copied to the /uk, /au, /nz, and /sg sites. I won't bore you with the details but the variation tool was deemed too blunt for our requirements and one of the developers on my team wrote a custom variation tool to do exactly what we want. The custom variation tool copies sub sites and pages but unfortunately it doesn't copy documents in document libraries; we don't make extensive use of the Documents library you get when you create a new publishing site but a few speicific sites do contain PDFs that need to be pulled over.

Since a document library is a list at heart, I started by examining the SPList API, assuming it would provide me with everything I need to manage the list items. I also looked into the SPListItemCollection returned by the Items property of SPList, and the SPListItem class. SPList was pretty hopeless. SPListItemCollection was somewhat more helpful, exposing the standard Add, Delete, and Count methods, and SPListItem was really enticing with its CopyFrom and CopyTo methods. Of course this was nearly a complete waste of time as few of these methods and properties really helped out at all. CopyFrom and CopyTo failed at runtime, Delete works as advertised but SPListItemCollection does not overload the Delete method or provide a sister method to delete everything in the list, and Add only adds a new list item if you get the very confusing url parameter pointing at the right location (a quick hint: it's expecting the URL of the destination file in the case of a document library...).

When it was all said and done, I'd written my own ClearList helper method, cast my destination list to a SPDocumentLibrary, accessed the Files collection via the RootFolder property of said document library, and passed in the byte array representing the uploaded file.

Here's the code I ended up with to copy the contents of the Documents list in one sub site to the Documents list in another sub site within the same web application:

using (SPSite site = new SPSite ("http://dev-moss-mh:101/"))
{
using (SPWeb sourceWeb = site.AllWebs ["Source_Site"])
{
using (SPWeb destinationWeb = site.AllWebs ["Destination_Site"])
{


SPList sourceDocuments = sourceWeb.Lists ["Documents"];
SPList destinationDocuments = destinationWeb.Lists ["Documents"];


if (sourceDocuments.ItemCount > 0)
{
ClearList (destinationDocuments);


foreach (SPListItem currentSourceDocument in sourceDocuments.Items)
{
Console.WriteLine ("Adding: {0}", currentSourceDocument.Name);


byte [] fileBytes = currentSourceDocument.File.OpenBinary ();

const bool OverwriteDestinationFile = true;
string relativeDestinationUrl =
destinationDocuments.RootFolder.Url +
"/" +
currentSourceDocument.File.Name;

SPFile destinationFile =
((SPDocumentLibrary) destinationDocuments).RootFolder.Files.Add (
relativeDestinationUrl,
fileBytes,
OverwriteDestinationFile);
}
} } } }


As you can tell by the variable name, the Add method requires a relative URL pointing within the context of the destination site. This seems odd to me since Add ( ) is called on the destination list itself--why it can't figure out the destination URL is beyond me.

My ClearList implementation is also mildly interesting: deleting items within a foreach loop is obviously a no-no since the foreach syntax in C# is interacting with an IEnumerator object so my first attempt was to iterate over the list using a for loop and deleting list items from the zero index through to the final item in the list. This worked but only sporadically, occasionally leaving items behind. Calling ClearList a second time did the trick with a small list but that's just weird programming.

The solution I arrived at is detailed below and essentially comes down to the fact that the SharePoint list API must maintain a real-time (or part-time) connection with the database; in other words, deleting an item at index zero could mean SharePoint re-fetches the list content so by the time my for loop moves on to the next index, the list has effectively shuffled itself down so index zero is still populated. As you can see, I'm now simply iterating over the list and always deleting the item at index zero. I could have possibly used a while loop and the listToClear.Items.Count property directly but it's difficult to know whether SharePoint can be trusted in a case like this. I'll leave that up to you to try out...

private static void ClearList (SPList listToClear)
{
int initialItemCount = listToClear.Items.Count;

for (int counter = 0; counter < initialItemCount; counter++)
{
// Always delete the list item at index 0
SPListItem listItemToClear = listToClear.Items [0];
listItemToClear.Delete ();
}
listToClear.Update ();
}
 
 
 

Thursday, 8 November 2007

Clear Your Compiler Warnings

There’s a minor problem with this code—at least as far as the compiler’s concerned. Can you spot it?
...
catch (Exception ex)
{
// Don’t do anything
}
The problem is this: the ex variable is declared but never used and the C# compiler will warn you of the fact.

warning CS0168: The variable 'ex' is declared but never used

Does this matter in terms of how the code runs? Of course not but what if everyone always did this and the explosion of compiler warnings masked a more important warning relating to something else? Building the wa.com solution spits out 56 warnings—42 of which have to do with variables never being used—and the entire warning mechanism provided by the compiler is therefore of very little use to us. If it weren’t for this mess, someone might have noticed this fairly useful warning before now:

warning CS0162: Unreachable code detected

There’s an easy way to get around this problem when it comes to exceptions... just don’t declare the exception variable. This example does exactly the same thing at runtime but compiles without the warning. If you need to inspect the exception while debugging, use $exception in a watch.
...
catch (Exception)
{
// Don’t do anything
}
For all other warnings to do with undeclared or unassigned variables, delete the offending declarations!

As for the example catch statement above, you all know this is bad, bad, bad (in all but the most extreme circumstances), right? Bugs disappear into black holes like this and a more specific exception, at the very least, should be caught instead. A better way would be to remove the try/catch statement, test thoroughly to flush out the defects in your code, and reserve exceptions for truly exceptional circumstances.

Tuesday, 28 August 2007

Generating Public, Strongly-Typed Resource Classes with Visual Studio

Visual Studio 2005 does a great job of managing your .resx files and automatically generates strongly-typed classes exposing the contents of those files. If you create a new resource file and add it to your project you'll notice the Custom Tool property has a value of ResXFileCodeGenerator to suppor this behaviour.

This is generally all well and good but there is a catch: ResXFileCodeGenerator generates classes with members marked internal; in other words, you won't be able to access your resources using the generated class if you're working in another project (i.e. another assembly).

The resgen.exe tool does all the hard work behind the scenes and does have a flag called PublicClass that will override this behaviour--set this flag and your classes will be generated with public visibility. Unfortunately you can't run this tool automatically until compile-time, which means your resources won't be as conveniently accessible as they are by default; you'll also have to write a post-build script or use another method to do all the hard work moving your generated files around.

Luckily Visual Studio 2008 solves this problem by allowing you to set the Custom Tool property to PublicResXFileCodeGenerator. As the name suggests, the generated methods come out the other end marked as public and this all happens from within Visual Studio.

If you really can't wait for Visual Studio 2008 (and it's not far away), you may want to look into a handy little extension called ResXFileCodeGeneratorEx. In addition to allowing you to create publically-accessible, strongly-typed classes for your resources, it also helps out if you're dealing with format strings in your resource files. The only downsides I can think of are the fact that Visual Studio 2008 will make this tool less necessary (apart from the format bit) and that every developer will need to install it on their machine. No biggie but the sort of thing that can cause headaches for new developers joining your team.

Thursday, 9 August 2007

Creating a Custom CultureInfo

The System.Globalization.CultureInfo class comes with a number of pre-defined cultures but thankfully Microsoft recognises it hasn't supplied all culture/language combinations (real or imagined) and will allow you to build your own. One way you can do this is using the System.Globalization.CultureAndRegionBuilder class.

We ran into trouble while attempting to localise the westernaustralia.com English-language sites targeted at specific regions (we've got a "global" EN site, a "domestic" AU site, and UK, NZ, and SG variants). .NET 2.0 (and Windows XP/Server 2003) define CultureInfos and locales for all of our language/region combinations except for Singapore; the closest in-built option we could find was zh-SG (which is Chinese/Singapore). Although we could have cheated and used zh-SG, we're also running a number of foreign-language variations of the site; to be explicit, avoid confusion, future-proof this aspect of the site, and--most importantly--to make use of .NET's resource fallback mechanism (from en-SG to en), we decided to define a custom CultureInfo.

While creating a new CultureInfo isn't a difficult task, it's not as easy as supplying an "en-SG" string to the CultureInfo constructor or deriving a new class from the CultureInfo class (you can derive a new CultureInfo from an existing CultureInfo, however).

CultureInfo ci = new CultureInfo ("en-SG"); // This will fail at runtime
internal class MyCultureInfo : CultureInfo // There's an easier way...

MSDN provides a succinct article on building a custom CultureInfo class and trust me, it's really quite easy. The article fails to mention that you need to add a reference to the sysglobl assembly to gain access to the CultureAndRegionBuilder class so as long as you remember that step you should be fine. The sample provided also prefixes the new CultureInfo with "x-" and I think this is a great idea: doing so should avoid any conflict when you move to the next version of the .NET Framework or a new platform. Vista and, presumably, Server 2008, include the en-SG locale so naming our new CultureInfo "x-en-SG" means we can anticipate a smooth transition if the existing wa.com code is ever moved to Windows Server 2008.

You don't need to create and register a new CultureInfo every time your application runs (and you probably don't want to since the CultureInfo is written to the filesystem when its registered and invoking Register () again will fail) so we've built the create/register code into our deployment script. We simply try to unregister the existing CultureInfo, create x-en-SG from scratch based on the en-US CultureInfo and the SG RegionInfo, and register the new CultureInfo. Our English-Singapore .resx files reflect the new CultureInfo and are named as though x-en-SG were an in-built CultureInfo: *.x-en-SG.resx.

Broken .resx files in Visual Studio 2005/.NET 2.0

Working with resources is so much easier in .NET 2.0 but things do occasionally go awry. Most of the time the problem is really easy to fix.

As discussed in another post, Visual Studio 2005 does a lot of work behind the scenes to surface your resources as strongly-typed objects; if you're not careful with your .resx files, however, you might end up in a situation where your .resx files aren't being compiled for you. As a result, you lose Intellisense for your resources, the ResourceManager may end falling back to your default resource file when it shouldn't, or your default resource file might not load at all. Copying and renaming Visual Source Safe-controlled .resx files is one little culprit that occasionally brings everything to a halt.

It's important to remember Visual Studio doesn't just "do" things for you--it must be told what to do and frequently relies on stand-alone tools included with .NET or sitting outside of the VS shell. A good example of this can be seen by inspecting the property sheet (in Visual Studio) for one of your .resx files.

When you create a new .resx file Visual Studio does all the right things by setting the Build Action to "Embedded Resource" and setting the Copy to Output Directory as "Do not copy". Just as importantly, Visual Studio also sets the Custom Tool property as "ResXFileCodeGenerator" and this particular setting can occasionally get stripped away when you're renaming or moving resource files. If in doubt and your resources are not being made available to your application, check this property; if it's not set, set it to "ResXFileCodeGenerator".

If the Custom Tool property on your .resx files is set correctly, Visual Studio will help you out by running the specified tool for you every so often to ensure your resources are available programmatically (this can actually be a pain in the neck sometimes so I recommend using a tool like Resourcer to edit your resource files...). If this isn't happening, you can simply right-click on your .resx file in Visual Studio and select Run Custom Tool.

Thursday, 31 May 2007

Localizing Web Parts, Custom Controls, and Class Libraries

If you've dealt with the ResourceManager in .NET 1.x--or never touched resources altogether, moving to .NET 2.0 simplifies the process to the point where it all seems too simple. Simplicity is generally a good thing, of course, and once you understand localization in .NET 2.0 you'll probably agree there's no reason why pretty much every application shouldn't be localized from the beginning (I'm in the process of localizing and existing MOSS 2007 site, hence the sentiment just expressed).

Localization is a good thing because it:

  • Allows you to refactor hard-coded strings for labels, menus, and so on out of your code and into .resx files;
  • Enables your application to display a user interface relevant to users of different languages.

Localization won't translate your interface for you--that still has to be done manually.

Visual Studio 2005 now takes care of all the hard work needed to develop a fully localized app in no time at all. Firstly, it provides a convenient designer for creating resource files through which you can add strings, images, icons, and text/script files. Secondly, any .resx file added to your project are automatically compiled to a .resources file and linked to your main assembly. Finally, a resource file wrapper class is generated automatically, granting you strongly-typed access to the contents of your resource files. What more could you ask for?!?

Working with resources is really straight forward if you're writing user controls or web pages (apparently WinForms are just as straightforward but I don't know much about WinForms) because both the UserControl class and Page class both derive from System.Web.UI.TemplateControl. TemplateControl exposes the protected GetGlobalResourceObject ( ) and GetLocalResourceObject ( ) methods. When a user control or web page has a resource file available to it, you also get strongly-typed access to the file like this:

Resources.MyResourceFile.MyKey;

(where 'Resources' is some weird namespace that only comes to life when you've got .resx files in your project)

On the other hand, if you're writing web parts, custom controls, or class libraries, you're probably not deriving from TemplateControl (especially in the web part case where you class inherits WebPart). You can still add resource files to you project and use a ResourceManager to pull out the stuff you need but there's an easier way.

  1. Create a new class library project; name it MyCustomWebParts or whatever you like. The name you give your project will also become the name of the assembly and be used as the default namespace for any classes you add and any classes added by Visual Studio (this last bit is really important).
  2. Create a new resource file (Add new item...) named strings.resx in the root of the project (you can also place your resource files in an arbitrarily-named folder but doing so will change how the file is accessed programmatically). Add a new string with a name of labelText and a value of Hello World.
  3. Create a new class that derives from
    System.Web.UI.WebControls.WebParts.WebPart; name it MyWebPart or whatever you like.
  4. Add a CreateChildControls ( ) method to your class and within the method body, instatiate a new Label object and add it too the Controls collection.
  5. Immediately after the Label is instantiated, set its Text property from the resource file. You do this by referencing [the default namespace for the assembly].[the name of the resource file with no extension].[the resource key name].
  6. Add or update a globalization element to your web.config file and set both the culture and uiCulture attributes to auto:
    <globalization uiculture="auto" culture="auto" />
    This works on a regular ASP.NET site but MOSS doesn't automatically assign the browser's current language to the System.Threading.Thread.CurrentThread.CurrentCulture and CurrentUICulture properties so you may wish to do this yourself and forego the above web.config setting.
  7. Build the project and register the web part in a .aspx page--and that's it!

namespace MyCustomWebParts
{
public class MyWebPart : WebPart
{
protected override void CreateChildControls ()
{
Controls.Clear ();
Label label = new Label ();
label.Text = MyCustomWebParts.strings.labelText;
Controls.Add (label);
}
}
}

As mentioned, adding a .resx file to your project prompts Visual Studio to generate a strongly-typed wrapper class for accessing the file; this class is created in the project's default namespace. If your web part or control is the same namespace you don't need to qualify your resource file within the MyCustomWebParts namespace--you can access it directly: strings.labelText. If you've got multiple namespaces in your project (or not) it's probably a good practice to always qualify the resource class name.

If you do drop your .resx files into a folder you'll need to modify the way you reference them:

MyCustomWebParts.MyFolder.strings.labelText;

Either way, IntelliSense will help you out as you go if everything's in the right place.

To tweak performance, you can tell ASP.NET which resources are contained in the default assembly by adding an attribute to your class library's AssemblyInfo file:

[assembly: System.Resources.NeutralResourcesLanguageAttribute ("en")]

And the end result: localized web parts, custom controls, and class libraries. Cool.

 

Sunday, 25 March 2007

XmlSerializer and minOccurs="0" collections: that pesky xxxSpecified magic

I'm attempting to decorate the properties in a class so when it's serialised by the XmlSerializer, it adheres to a schema that looks, in part, like this:

<xs:element minoccurs="0" name="Locations">
<?xml:namespace prefix = xs /><xs:complextype>
<xs:sequence>
<xs:element name="Location" maxoccurs="unbounded" type="xs:string">
</xs:sequence>
</xs:complextype>

Basically, I've got a class that contains a Locations collections; if the collection has one or more items, it should be serialized and if it has zero items, it shouldn't be serialized and, most importantly, the Locations element should NOT appear in the serialized document.

Running the property below through the XmlSerializer works fine if the collection is populated but results in an empty element if the collection is empty.

So this:

[System.Xml.Serialization.XmlArrayItemAttribute ("Location")]
public List Locations
{
get
{
return SearchAttributes.Locations;
}
}

populated at runtime with zero items results in this:

<locations>

And schema validation fails.

I've looked at various attributes trying to find something that will optionally serialize an element or collection but nothing jumps out.

XSD.exe produces the following property from the schema but by itself does nothing to help out here.

[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("Location", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public string[] Locations {
get {
return this.locationsField;
}
set {
this.locationsField = value;
}
}

Another XSD example produced an xxxSpecified property for a minOccurs="0" element (not a collection) and setting it false does remove the element from the output; I can't figure out why this works though! Sticking it into my own class does some sort of magic though:


private bool locationsSpecified;

[System.Xml.Serialization.XmlIgnoreAttribute ()]
public bool LocationsSpecified
{
get
{
return this.locationsSpecified;
}
set
{
this.locationsSpecified = value;
}
}


The LocationsSpecified property is simply set by the caller and voila, Locations disappears if empty.