Copy/paste internet code kills. Runtime comments on .net development, SharePoint WCM, and software engineering
Tuesday, 15 January 2008
Free MS Press eBooks: AJAX, LINQ, Silverlight
Get the Free Visual Studio 2008 e-Book Offer
"The offer includes the entire contents of Introducing Microsoft LINQ, as well as sample chapters on related technologies from Introducing Microsoft ASP.NET AJAX for Web Developers and Introducing Silverlight 1.0."
SharePoint Server 2007 SDK (SP1 Dec 07 Refresh)
http://msdn2.microsoft.com/en-us/library/ms550992.aspx
Oddly enough the link seems to be to the SDK from last August...
Wednesday, 9 January 2008
Google Apps Uncovered
My domain name registrar (Planet Domain) allows me to assign name servers and create child domains pointing to an IP address—basically an A record. As I wasn’t using Planet Domain for hosting the mediawhole.com site that’s all they would allow me to do, aside from renew my domain and update my registration details. A query to their helpdesk suggested my web host would be the best place to create CNAME record.
I was previously using atspace.com to host mediawhole.com. atspace provides free web hosting with no ads, FTP access, and POP3 email. Apart from those goodies, they also limit the size of file uploads to something ridiculous like 200KB. At any rate, the atspace interface allowed me to create the blog.mediawhole.com sub domain (what that resulted in at the DNS level, I’m not quite sure—I never checked).
While reading up on DNS and CNAME records, I came across a help page from Google Apps; little did I know my web master world would soon change instantly. What on earth is Google Apps, I asked myself, and proceeded to do what I could to find out. In typical Google fashion, the Google Apps homepage is a little blah and at first glance I figured it was a paid for service (a paid for service from Google? Isn’t everything from Google free?!?). Digging deeper, I discovered there is a free version and the major differences between the free version and the paid for version is the support on offer and the rather large limits on what you get (users, storage capacity, etc).
I signed up to have a looksee and soon realised Google Apps integrates a basic content management system, email via Gmail, calendars, IM, a user management system, a document repository that works with Google’s online document editing suite, and a few other goodies. Most of these features are all beta software. Apart from that, Google Apps gives you the opportunity to create and manage your very own (albeit, web-based) enterprise. You can effectively brand Google to a limited degree so it looks at home on your intranet, create user accounts with corresponding email addresses, create email lists and email address aliases, share your calendars, publish a public web site, and manage documents. The fancier offerings even offer a single sign-on feature.
The best feature of all is the option to use your own domain name for all of these services for a unified, professional appearance. Forget the blog, I was going to move my entire Google Apps suite to mediawhole.com! Just like blogger, Google Apps allows you to create various CNAME and MX records pointing to ghs.google.com (in the case of the CNAME records); the individual apps are then assigned to those URLs.
Planet Domain and atspace, I realised, weren’t going to help much with this. Planet Domain was a basic starting point for my name servers but I really needed control over all the DNS records for my domain. Although Google provides all the Apps stuff, they don’t provide any form of DNS management. Many of the Blogger and Google Apps instructions feature Go Daddy so I thought transferring my domain name to Go Daddy might also give me a better control panel for this sort of thing. They were also offering a free year of registration on top the time remaining on my current registration for seven bucks so I thought it might be worth it.
While I waited for Go Daddy support to reply to my email query, I Googled free DNS to see what might be available. I was in luck as I discovered, everyDNS.net, among other free DNS hosts. The web sites for these free DNS providers are atrocious (I’m not joking—they’re all very 1996) so I have no idea how reliable they or how long they’ll be around. Many DNS providers claim to host many thousands of records and offer globally distributed redundant records so I pretty much took a punt on everyDNS.net.
To get up and running, I firstly had to set my name servers to point to the everyDNS.net name servers. I did this through Planet Domain and was surprised to see how quickly the update took hold. Instead of twenty four to forty eight hours, my name server configuration changes were available almost immediately—within half an hour max. That was great as it allowed me to create my CNAME and MX records through the everyDNS.net interface and test my changes in real-time (with the name servers configured, all of my other records are resolved through everyDNS.net so any subsequent additions or modifications are instantaneous because everyDNS.net doesn’t have a waiting period for record propagation). One by one, I walked through the Change URL wizard for each of the Google Apps, creating DNS records as instructed in the very decent Google Apps help section. The mediawhole.com site now looks like this:
http://www.mediawhole.com – the Google-hosted content management system for the site
http://mail.mediawhole.com – the Google-hosted email system for the site
http://calendar.mediawhole.com – the Google-hosted calendar system for the site
http://documents.mediawhole.com – the Google-hosted document repository for the site
http://intranet.mediawhole.com – the Google-hosted, Mediawhole-branded search page for the site
http://blog.mediawhole.com – this Blogspot blog
As I worked, I used a handful of tools from some DNS-oriented sites to verify my changes.
networktools.com - DNS lookup, ping, and other useful tools
hscripts.com - DNS lookup and other bits and bobs
MxToolbox.com - Specific MX record lookup
The ping and tracert commands in Windows also come in handy. At one point I thought I also needed to flush my local DNS cache, for which I used ipconfig /flushdns
With email configured, I also set up a few email accounts for the people involved in mediawhole.com and some generic email aliases (support, helpdesk, info, sales, and a catch-all) delivering mail to my account.
Finally, I jumped into the web page editor, chose a template for the site, and started plugging in some basic content. The editor allows you upload pictures and files, edit the HTML directly, and add gadgets. It’s generally fairly basic (I haven’t come across a way to reuse content—like a footer—between pages) but the templates and three layout options do the trick. Unfortunately Google Apps doesn’t allow you to connect via FTP but in this day and age that’s a minor niggle.
This is a great tool for individuals, small businesses, schools, and community groups that might otherwise struggle to maintain the hardware and software to support a suite of functionality this comprehensive. I had the mediawhole.com site up and running in an evening (around four hours before sitting down to put in any real content). It will be interesting to see what new apps are added to Google Apps over time; the basics are all there now but I’m sure those Google heads will keep pushing.
Incidentally, Microsoft Office Live has also been rolled out in the US. The online marketing material suggests it’s a very similar offering but I haven’t been able to test it out as the beta is only open to residents of the US. If there are any other similar suites out there, please let me know.
Thursday, 3 January 2008
C# Switch Fallthrough with goto
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)
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.
Monday, 24 December 2007
Blogger Code Formatting
I like blogger in general but it's probably not the standard geek's first choice; I suggest this simply because the editor has no UI functionality to preserve the formatting of the code samples most geeks want to paste in. HTML, God bless it, is HTML and Blogger doesn't help you write anything more than basic HTML. Moreover, Blogger's line break "helper" apparently interferes with the old standby tricks like pre, code, and blockquote. I say apparently because either there are a lot of untested myths out there or Blogger has changed how it deals with these tags over time.
So, to get my code samples to paste in effortlessly and to set the story straight, I present below the way I learned to beat the blogger editor and it's as simple, as--wait for it--the trusty pre tag. To paste in the sample below, I simply dropped into HTML mode, pasted in the class definition, wrapped it in a pre tag and fixed up a few line breaks. In my case, I've got the Convert line breaks option (Settings --> Formatting) set to to Yes.
Definitely better than before but pre does not preserve HTML and XML fragments and Blogger simply removes them from the post. The problem here lies mainly with the HTML and XML bits that look like HTML--I'm talking mainly about less than and greater than brackets. To get around this, I simply use an HTML encoder to drop in my markup, encode it, and then copy the output into Blogger. It's a pain but what can you do...
class Base
{
public virtual void DoWork ()
{
Console.WriteLine ("Base.DoWork");
}
}
Tuesday, 18 December 2007
Visual Studio Spell Checker
http://blogs.msdn.com/webdevtools/archive/2007/12/13/spell-checker-for-html-asp-net-jscript-vb-c-css-and-c-for-visual-studio-2005-and-2008.aspx
Sunday, 16 December 2007
Senior Developer Interview Questions
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
- Describe the difference between the execution environments for C++, C#, and Javascript
- Is C# a weakly-typed language? Why or why not?
- When should performance optimisation occur?
- 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;
}
} - When would you mark a class with the internal visibility modifier?
- What’s the difference between a struct and a class? Are structs allocated on the heap?
- 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...
- 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 - 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:
- What is a use case?
- Briefly describe the difference between a class, an interface, and a type
- 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.
- 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...
- 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
- 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.
- Will the Hello World! text be rendered green, red, or blue by the browser?
<style>
span { color: green }
#makeItRed { color: red; }
.makeItBlue { color: blue; }
</style>
<span id="makeItRed" class="makeItBlue">Hello World!</span> - List three key components of this schema fragment. How many ReservationRequest elements are allowed in an XML document validated against this schema?
<xs:element name="Control">
<xs:complexType>
<xs:sequence>
<xs:element name="ControlID" type="xs:int" minOccurs="0" />
<xs:sequence minOccurs="0">
<xs:element name="ReservationRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="InDate" type="xs:dateTime" />
<xs:element name="Period" type="xs:int" />
<xs:element name="Adults" type="xs:int" />
<xs:element name="Children" type="xs:int" />
<xs:element name="Infants" type="xs:int" /> </xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
Sound knowledge of the Microsoft .NET framework class libraries, ASP.NET and Web Services
- What improvements does the .NET 2.0 System.Collections.Generic namespace offer over the System.Collections namespace from previous versions of the framework?
- List two key differences between a user control and a web control
- Compare the .NET application cache and the ASP.NET output cache
- 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 - Describe the difference between application state, session state, and view state. Discuss session state in relation to scalability and suggest an alternative.
- List two techniques to secure web service communication on the internet
Ability to perform unit and integration testing...
- What purpose do the following serve when debugging a section of code:
· The F11 key on your keyboard
· The Immediate window - Briefly describe the concept of “regression testing”
Copying a SharePoint Document Library Programmatically
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, 13 December 2007
LastModifiedIndicator Kind of Works
The control in question can be dropped into a page layout or master page using the following syntax:
When the page is served, my local dev server displayed the text below (I'm guessing this display format is relevant to the regional configuration of the server):
12/14/2007 2:24 AM
The LastModifiedIndicator class is derived from WebControl and exposes no additional properties or methods to configure the format decoratively. This would obviously be quite handy because the next best "quality" alternative is probably to implement your own LastModified webpart. The format displayed above will be unsuitable in many cases; although I haven't played with the control's output at any length, a quick and easy hack might be to access the last modified string on the client side and use a bit of JavaScript to reformat its contents using the JavaScript date functions. Definitely not pretty but a little less heavy-handed than building your control or getting in there with some server side code.
You may have noticed a time of 2:24AM in the sample output I listed above; no, I'm not a late night hacker! I actually modified the test page I was working on at 11:24AM on 13 December 2007 but my dev server was telling me I modified it at the unwholesome hour of 2:24, one day in the future. I wish I could do that... or SharePoint would allow me to do that but no luck there so far. Anyway, I haven't tested this solution yet but the legendary Tania down the road from Tourism indicated she got the control to behave by "changing the regional settings of the site and all subsites to Australia and then changing to GMT." I'm not sure exactly what that means but I'm assuming she fiddled with the site settings.