Archives

Archives / 2005 / March
  • Code Structure with VS2005 Using Partial Classes

    Thanks to Trent on suggesting to use a partial class for implementing the auto-code part of a class from yesterday. I thought the idea of partial classes was neat but the only thing I could think of was where you had a large class so you split it up into logical components for multiple people to work on at the same time. Personally I wouldn't let my classes get that big but you never know on a large system. However it seems perfectly suited for this type of separation. Okay, maybe so I'm not the first to explore things to do with partial classes when you're bored. Cut me some slack for being a year late to catch up on things and check out:

    Making Sense of Partial Classes
    Create Elegant Code with Anonymous Methods, Iterators, and Partial Classes
    Understanding and Using Partial Classes

    Here's a sample class split up into two files. UserCG.cs and User.cs. One is for interacting with the Class Designer and the code it generates. The other is for hand coding your Domain logic.

    /// <summary>

    /// This part of the class has the code generated fields and properties.

    /// </summary>

    public partial class User

    {

        public User()

        {

        }

     

        private string name;

        public string Name

        {

            get

            {

                return name;

            }

            set

            {

                name = value;

            }

        }

     

        private string emailAddress;

        public string EmailAddress

        {

            get

            {

                return emailAddress;

            }

     

            set

            {

                emailAddress = value;

            }

        }

    }

     

    /// <summary>

    /// This part of the class has the coding implementation.

    /// </summary>

    public partial class User

    {

        public void DomainMethod()

        {

        }

    }

     

    It's not perfect as you may want to use the Designer to add a bunch of methods that should be in the Domain logic but then you could just add those by hand and keep your fields, properties and interface implementations in the UserCG.cs file. Just right click on the Class in the Designer, choose Properties, then specify which source file any new members added to the class will be added to through the New Member Location property. So now you can keep all the frilly stuff out and put your Domain logic in a single file for your class. Of course some people will recognize this as it takes me back to the old days when we had an Implementation and Interface file from our Delphi/Turbo Pascal days. Very slick none the less.

  • Changing the way you code, physically?

    I've been doing a tremendous amount of work with VS2005 lately (and getting all our ducks in a row to set things up to embrace it, this isn't just another software upgrade kids) and noticed something funny that I wanted to ask people about.

    Currently we generally follow a standard on how we organize our class code inside. Specifically the ordering of how this appear in a class, adding regions surrounding them, etc. This is our basic layout for a simple class:

    public class User

    {

           #region Fields

           private string name;

           #endregion

     

           #region Constructors

           public User()

           {

           }

           #endregion

     

           #region Accessors

     

           public string Name

           {

                  get { return name; }

                  set { name = value; }

           }

     

           #endregion

     

           #region Methods

           #endregion

     

           #region Private Methods

           #endregion

    }

     

    Generally the meat is in the middle with the public methods. Private methods live down below hidden in a region, fields up top, etc. It basically gives us some organization when jumping around in the code. Grant you these days people use the drop down method list or navigators like ReSharpers.

    When using VS2005 you have the option (it's not forced thank god) to create your classes using the Class Designer. Here's our class created with it, all pretty and nice, in the happy new designer:

    And here's the code generated behind it:

    public class User

    {

           private string name;

           public string Name

           {

                  get { return name; }

                  set { name = value; }

           }

     

           public User()

           {

           }

    }

     

    Notice something huh? The Name field was added first then I decided to add a constructor. So the code follows it the way it was entered in the designer. Even after all that (or if you created the code manually) when you say add a new string field called emailAddress then using the refactoring tools to encapsulate it you get something like this:

    private string emailAddress;

    public string EmailAddress

    {

           get

           {

                  return emailAddress;

           }

     

           set

           {

                  emailAddress = value;

           }

    }

     

    So Microsoft chose to group the private field with the public accessor. Sounds kind of sane. 6 of one, half a dozen of another. Just wondering if this is going to bug anyone where the codebase reads differently (at least from an organization point of view) than what they might currently do. Is it time to start changing our code organization efforts to accomodate for this so we don't end up with some code looking one way and some looking the other?

  • Fix ONET.XML and win a prize!

    Cheap huh? Okay after yesterdays ObjectMother fiasco I think I've calmed down now. Thanks to those who posted the comments and information. I always find it hard to get good examples of unit testing out there and it's always hard to know what to test. All the TDD examples I've seen are so simple and the some of the examples you can find are usually large frameworks that are generally testing infrastructure. There doesn't seem to be a good set of samples out there that actually tests business objects.

    Anyways, back to SharePoint and how I adore ONET.XML and all it's happiness. Here's a simple challenge for someone with more Xml skills than I do (which isn't saying much).

    We all know (or should know) we can embed Web Parts on a page and automagically have them populate the pages when a site is created using the <AllUsersWebPart> tag in the </Project/Modules/Module/File> section of ONET.XML. The contents of this tag is essentially the DWP you would see from an exported Web Part. Take any Web Part, export, copy and paste into ONET.XML and Bob's your uncle. For the Content Editor Web part, this Xml fragment is surrounded by a CDATA tag. Okay, everyone's on the same page so far. Good.

    The challenge is that when you export the Content Editor Web Part it embeds a second CDATA tag for the actual HTML content you created. The problem is that the result in ONET.XML isn't valid Xml and when the site gets created an error is thrown. Here's the Xml that causes problems:

    <AllUsersWebPart WebPartZoneID="PageTitle" WebPartOrder="1"><![CDATA[<WebPart xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/WebPart/v2">
    <Title>My Title</Title>
    <FrameType>None</FrameType>
    <Description>Use for formatted text, tables, and images.</Description>
    <ZoneID>MyZone</ZoneID>
    <Assembly>Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
    <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
    <ContentLink xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
    <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><![CDATA[<div class="ms-pagetitle">My Text Here</div>]]></Content
    >
    </
    WebPart>]]></AllUsersWebPart>

    The problem occurs after the content (My Text Here) and the "]]". SharePoint (and any Xml editor) thinks this is closing off the first CDATA that was created up at the beginning of the <AllUsersWebPart> tag.

    So what should be the fix? Post your answer in the comments and I'll verify it later today. Winner gets a free copy of Enterprise Integration Solutions by Devin Spackman and Mark Speaker.

    Update: We have a winner! Jim Duncan was the first to point out to remove the embedded CDATA tag and encode the HTML within the <Content> tags. Here's the corrected Content Editor Web Part that you can embed in an ONET.XML file:

    <AllUsersWebPart WebPartZoneID="PageTitle" WebPartOrder="1"><![CDATA[<WebPart xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/WebPart/v2">
    <Title>My Title</Title>
    <FrameType>None</FrameType>
    <Description>Use for formatted text, tables, and images.</Description>
    <ZoneID>MyZone</ZoneID>
    <Assembly>Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
    <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
    <ContentLink xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
    <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><&lt;div class="ms-pagetitle"&gt;My Text Here&lt;/div&gt;</Content
    >
    </
    WebPart>]]></AllUsersWebPart>

  • Advantages to using an ObjectMother and Why should I test string = string.Empty?

    In my never ending quest for the holy grail I continue to ask more questions than I answer. Recently as I was putting together our unit tests for a project, I decided to give the ObjectMother pattern a whirl. This is a pattern dreamed up by some ThoughtWorkers and is a simple, scalable framework whose sole purpose is to construct and facilitate the customization of test objects. ObjectMother manages the lifecycle of test objects including creation, customization and, when necessary, deletion. I think it's an interesting pattern but is there a real advantage to using it over just creating and initializing objects in your test [Setup].

    Lets say your have a Task class in your Domain that manages tasks for users. Here's our Task class:

    public class Task

    {

          private string name = string.Empty;

          private string owner = string.Empty;

          private DateTime dueDate = DateTime.Now.AddDays(7);

          private DateTime notificationDate = DateTime.Now;

     

          public Task()

          {

          }

     

          public string Name

          {

                get { return name; }

                set { name = value; }

          }

     

          public string Owner

          {

                get { return owner; }

                set { owner = value; }

          }

     

          public DateTime DueDate

          {

                get { return dueDate; }

                set { dueDate = value; }

          }

     

          public DateTime NotificationDate

          {

                get { return notificationDate; }

                set { notificationDate = value; }

          }

    }

    There are some requirements the business tells us that we want to test against.

    • The due date must be greater than the notification date
    • A task must be assigned to someone
    • A task must have a name

    This leads us to building some tests that look something like this:

    [TestFixture]

    public class TaskTests

    {

          [SetUp]

          public void SetUp()

          {

          }

     

          [TearDown]

          public void TearDown()

          {

          }

     

          [Test]

          public void TaskCreation()

          {

                Task task = new Task();

                task.Name = "Release Windows under the GPL";

                task.Owner = "Bill Gates";

                task.DueDate = DateTime.Parse("12/31/2009");

                task.NotificationDate = DateTime.Parse("01/01/2010");

                Assert.AreEqual(task.Name, string.Empty);

                Assert.AreEqual(task.Owner, string.Empty);

                Assert.IsNull(task.NotificationDate);

                Assert.IsNull(task.DueDate);

          }

     

          [Test]

          public void DueDateAfterNotificationDate()

          {

                Task task = new Task();

                task.DueDate = DateTime.Now.AddDays(1);

                task.NotificationDate = DateTime.Now;

                Assert.IsTrue(task.DueDate > task.NotificationDate, "Due date must be after notification date.");              

          }

     

          [Test]

          public void DueDateBeforeNotificationDate()

          {

                Task task = new Task();

                task.DueDate = DateTime.Now.AddDays(-1);

                task.NotificationDate = DateTime.Now;

                Assert.IsTrue(task.DueDate < task.NotificationDate, "Due date cannot be before notification date.");              

          }

    }

    Using the ObjectMother pattern, I can initialize my task object with the appropriate values using static creators like so:

    public class ObjectMother

    {

          public ObjectMother()

          {

          }

     

          public static Task CreateTask()

          {

                Task task = new Task();

     

                task.Name = "Release Windows under the GPL";

                task.Owner = "Bill Gates";

                task.DueDate = DateTime.Parse("12/31/2009");

                task.NotificationDate = DateTime.Parse("01/01/2010");

     

                return task;

          }

    }

    And I modify my tests to check against values from the ObjectMother like so:

    [Test]

    public void TaskCreation()

    {

          Task task = ObjectMother.CreateTask();

          Assert.AreEqual(task.Name, string.Empty);

          Assert.AreEqual(task.Owner, string.Empty);

          Assert.IsNull(task.NotificationDate);

          Assert.IsNull(task.DueDate);

    }

    The traditional way of initializing my task object would be in the [Setup] method in my test class (using a private field called task of type Task) and initializing the values to some constant in my test. Alternately to the ObjectMother method above, I could create static fields in the ObjectMother the same way for comparision (or pass in values from the Test to the ObjectMother.CreateTask method to initialize them to known values). Here's the setup for my test in my [TestFixture]:

    private Task task;

    private string defaultTaskName = "Release Windows under the GPL";

    private string defaultTaskOwner = "Bill Gates";

    private DateTime defaultTaskDueDate = DateTime.Parse("01/01/2010");

    private DateTime defaultTaskNotificationDate = DateTime.Parse("12/31/2009");

     

    [SetUp]

    public void SetUp()

    {

          task = new Task();

          task.Name = defaultTaskName;

          task.Owner = defaultTaskOwner;

          task.DueDate = defaultTaskDueDate;

          task.NotificationDate = defaultTaskNotificationDate;

    }

    And my test would compare values to private fields of the test class which makes the creation test look something like this:

    [Test]

    public void TaskCreation()

    {

          Assert.AreEqual(task.Name, defaultTaskName);

          Assert.AreEqual(task.Owner, defaultTaskOwner);

          Assert.IsNull(task.NotificationDate);

          Assert.IsNull(task.DueDate);

    }

    So where is the advantage to using an ObjectMother? Rather than comparing values against the private fields in my TestFixture I could compare them against static fields in the ObjectMother class. Maybe the ObjectMother is for more complicated objects that need lifecycle management but then do I really want to mix object creation in my tests?

    More importantly, should I really compare a DateTime value to a DateTime value? Is that a valid test or am I testing the assignment of variables in the .NET framework. True, if you put logic into the Task class setter for DueDate and NotificationDate you can throw an exception so it doesn't allow invalid dates which would give me a more valid test. How many times have you seen this test:

    [Test]

    public void TestValidOwner()

    {

          task.Owner = "John Smith";

          Assert.AreEqual(task.Owner,  "John Smith", "Task Owner does not match");

    }

    I've just seen too many samples claiming that it's a valid test when all they're doing is comparing a string to a string (alternately getting the string from a const value in the test class instead). How much value does this test add to your system?

  • What's a Web Part for Anyways?

    Maybe I'm getting senile in my old(er) age. Maybe I'm just emotionally upset that my blog isn't listed on the usual ones for SharePoint. Maybe I'm just angry at the world. Anyways, I have to wonder about Web Parts and what is out there. Walk with me on this one. I look around and see lots of people writing new Web Parts which is great. But then I have to wonder is it really that great? Let's look at the classification of Web Parts that seem to be prevelant out there.

    Roll-ups
    These are things that rollup information from the current site. This can be documents on a site, list items (rolled up and presented into a chart), or a list of sub sites under a parent to create a dynamic site map. CorasWorks has this nailed down pat with their suites of tools (even allowing you to create your own rollup no matter what or where the content is). There are lots of others that do pretty much the same (both free and commercial).

    RSS
    So many feeders and consumers we have a plethora of choices in this area.

    Display User
    I don't know how many times I see the "How do I show the user his name" Web Part. The variation on this is to display all users (much like the Members Web Part) pulling information from AD, another site, a list, etc.

    Document Management
    Lets face it. Some of the document features of a doclib are pretty sad (like the inability to simply move a doclib from one place to another without enabling Explorer View that I can't stand). I've seen a few Web Parts including a recent one that presents a different view of a document library (a more Explorer like interface with a treeview and the details).

    Recent Updates
    A Web Part that shows what's been going on like documents posted in the last x days, lists updated, who visited, etc.

    Navigation
    Similar to the document management problem (and somewhat tied into the Rollups) is navigation. People seem to want different navigation so there are gobs of treeviews out there that show sites and subsites in every which way you can. This includes some other type of vertical navigation across an entire site like breadcrumbs and tabs.

    Search Enhancements
    A few of these have come out recently (including free ones from commercial vendors) basically enhancing the somewhat simple full-text search of WSS.

    Did I miss anything? Probably. There are others out there. The point here is there really substance. The top 5 components on Microsofts Component Directory? A training kit that Microsoft created, 2 Web Parts that are bundled in with Office downloads, an RSS feeder, and an admin tool. What is it that people want besides what is already out there because frankly, these things listed are pretty standard fare. Is the SharePoint Web Part space that barren already? Where is that "killer" Web Part we've all been waiting for?

    Or maybe the Web Part ideas are exhausted and what we really need are templates that cater to delivering complete solutions. Jim Duncan provided this through an experiment he did on building a blog site using WSS which looks awesome. Serge van den Oever (got your name right this time) also put together an enhanced dicussion list (still nothing as close to what I consider a discussion forum like phpBB, but great none the less). So maybe more list and site templates are what the community needs and not Web Parts? How about a Knowledge Base site template you can drop in and customize to your corporate needs. Or a Help Centre system complete with automated emails and ticket management. Not impossible to do and these templates can be built to adapt to anyones configuration if done correctly. Some of these solutions might contain custom Web Parts (like Jim's does) but again those are specialized for a specific purpose and not something anyone can use on any old Team site.

    The Web Part framework was designed to provide a well crafted and simple system where you could plug anything (yes, anything) into a Web Part Page and benefit from it. Are the only Web Parts worth building the ones that solve a very specific business need like pulling SAP data from a backend system or talking to your corporate database systems? Is there nothing that is general enough that everyone wants, needs, desires that a Web Part could provide for you? I have yet to see the burning conversations in the newsgroups on "If only I had a Web Part that did...". Wouldn't that make people leap up and start building it (I know I sure would). It just isn't happening. So has the Web Part outlived it's glamour and the honeymoon is over already?

  • Visual Studio 2005 and SharePoint

    In my ongoing attempt to try to leverage the 2005 tools with our SharePoint development I continue to make some headway (not much though). I'll probably have to shelve my ideas for awhile as it's getting more and more painful everytime I try to model something. I mean, all of our code is just .NET classes. The UI is represented by Web Parts but the designers are having a hard time understanding these concepts. The problem is twofold with the 2005 tools. First it doesn't recognize somethine like SharePoint where there's an application layer, Web Services, Web Parts, a set of .NET classes to access the system (the SharePoint object model), and a database behind the whole thing. Second is that it's hard to just represent a plain jane .NET assembly as a tier in your application architecture.

    In UML it's easy to put together a component called "Business Logic" then associate a few groups of classes (Domain Objects, DTOs, Services, Gateways, Mappers, etc.) with the component. That would all get deployed to a SharePoint server (or several of them) in a deplooyment diagram. In the Application designer I can only represent things for Web Services, Windows Applications, or Web Applications. Maybe I'm trying to drill down too deep but is it much to ask for a component that represents my Business Logic other than a "GenericApplication"?

    On the plus side, it does understand Web Services so I've created a template that represents all the SharePoint Web Services (both Portal and WSS) which I can reuse. It did a great job of creating a definition of the Web Service and it's handy as a re-usable component, of course we don't use Web Services to get the job done as we have to talk to the object model directly. I've started building my own DSL templates for the Application and Logical Data Center designers that work with my SharePoint setups (even going so far to try to get the deployment part started but there are other challenges with that). I'm sure Microsoft will come along and provide these themselves some day so mine are just throw away at this point, but at least it's starting to look and feel like SharePoint (even if I can't deploy a 2.0 solution to SharePoint until at least 2006).

    I'll see if I can get some pictures up of what I've done so far and where the challenges are. Of course give yourself at least a day to install, uninstall, and re-install your tools if you're moving from Beta 1 to the Technical Refresh. Even on a beast of a machine that I have for this (Xeon 3Ghz) its taking forever.

  • Is it DTO or Dto? FxCop can't decide.

    Okay, I give up. Sure this might be minor to some but it's bugging the heck our of me this fine morning. 

    FxCop is a great tool. Sure, there are sometimes a few too many warning messages that it yells at you with and sometimes it suggests stupid things but for the most part it's yet another good tool to use to give your assemblies a sanity check. I ran one of our systems through FxCop to see what would come up, if there was anything we majorly missed and if there was something we should go back and refactor.

    FxCop is just plain retarted when it comes to the Data Transfer Object pattern. We have a folder in our domain called DTO that appropriately holds any Data Tranfer Objects we create. Of course a folder in a .NET project creates a new namespace but that's fine. So we have our namespace called AppName.DTO (it's not AppName but you get the idea) and there are several DTO classes in there for a Project, a Task, etc. Naturally we named these ProjectDto, TaskDto, etc.

    So first FxCop didn't like the namespace AppName.DTO and complained with the LongAcryonymsShouldBePascalCased error. Fair enough. So that means we should renamed the namespace to AppName.Dto to make it stop complaining. However right afterwards it complained with the IdentifiersShouldBeSpelledCorrectly when it hit our ProjectDto class, moaning that it didn't recognize the token 'Dto' in the class name.

    So which is right?

    1. AppName.Dto.ProjectDto
    2. AppName.Dto.ProjectDTO
    3. AppName.DTO.ProjectDto
    4. AppName.DTO.ProjectDTO

    I can't seem to find a combination that FxCop won't complain one way or another between the namespace and class names.

    Update: Thanks to Joe for the clarification. It's not really FxCop that's braindead about Data Transfer Objects, it's the guy creating them (yeah, that would be me).

  • Documenting SharePoint Solutions with Whitehorse

    I'm currently trying to document (via reverse engineering and a some manual efforts) a .NET application built on top of SharePoint using Whitehorse. Whitehorse is the codename for the Visual Studio 2005 SOA tools (or maybe it's the codename for all of the new graphical designers in VS2005 I can never get that straight). Anyways, we have a SharePoint solution that is made up of a gaggle of Web Parts, a domain and various service and utility classes. Rather than using the normal UML markup for documenting our architecture (which I've already started) I wanted to give VS2005 a run for it's money and see how easy (or hard) it's going to be to move toward this. UML is nice and works but being a Microsoft shop, we're moving towards the DSL approach where the model is the system and away from the UML documentation model where it's just a pretty picture but not reality. My end goal here is that if I document the current (ASP 1.1/SharePoint) system now and it (somewhat) reflects reality then moving to a 2.0 based system where the model is <strong>real</strong> and not just a disconnected set of bits, I get a model of a system that works to show what the migration path will be like. It would make it easier if I took a regular ASP.NET app to do this, but I figured let's really challenge the system (even though VS2005 won't be out til later this year and SharePoint won't support .NET 2.0 until at least 2006).

    Anyways, using drag and drop it's easy to lay out a system with the new tools. You drag an ExternalDatabase onto the model and specify the connection, etc. This is all great as you can use the items from the toolbox. Only problem is that there's nothing I can use to represent a SharePoint site or system because it's a bit of a hybrid. It's UI <strong>and</strong> a data access component. There's a nice little wiget to drag a BizTalkWebService on the system (or just a regular ExternalWebService) but we're talking to SharePoint through the object model. What the heck do I use to represent this? A WebApplication? An ExternalDatabase? A GenericEndpoint? Anyone tried this or have some thoughts on modeling a solution where you're using various parts of Microsoft systems as essentially middleware?

  • New Toronto SharePoint User Group

    Eli Robillard flipped me a note about a new SharePoint User Group he's starting up in the Toronto area. The first meeting is April 13 so you have plenty of time to get it into your calendar. If you're in the Toronto area, drop by and say hi. His blog entry on it can be found here and the main User Group site can be found here so please RSVP via the website on the meeting invite so Eli knows how many pizza boxes to bring ;)

  • Keep the SharePoint Web Parts burning

    I don't normally blog twice in the same day, but I was talking to Mike Fitzmaurice about SharePoint Web Parts, Smart Part, ASP.NET 2.0, and migration strategies. He's posted a blog entry that is a sort of roadmap for WSS into 2006 and is an excellent summary of what's going on at Microsquishy. Basically in a nutshell, WSS "v3" is built on top of the ASP.NET 2.0 Web Part Framework and don't plan to use Whidbey Web Parts in SharePoint sites for at least a year. Definately don't deploy ASP.NET 2.0 on your current SharePoint infrastructure unless you're into pain and suffering.

    My advice is to crack open that preview copy of Whidbey and the 2.0 framework (when you have time), build some ASP.NET 2.0 Web Parts using the framework and get to know the new classes intimately. They are your friend and a powerful allie they are.

    You can check out Mikes full blog entry here.

  • Bob Mixon's excellent SharePoint / BPM Review

    Over the past month or so fellow SharePoint blogger Bob Mixon has been doing some evaluations with various business process management solutions. He based his criteria on a few things like a GUI for modeling the workflow (for non-developer type guys to get their hands dirty), integration into the core Microsoft infrastructure (including WSS and SPS) and integration with other tools like InfoPath, etc. The result? A fantastic scorecard that gives his overall ranking of the products and rankings on the various criteria he was evaluating against. A most excellent resource for those that are looking in this space and don't know what to do. I did find it interesting he didn't include BizTalk in his eval though. You can check out his blog entry here. Thanks Bob!

  • Web Parts and ASP.NET 2.0

    Dino Esposito has a nice summary article over at TheServer.NET on his thoughts around ASP.NET 2.0, the Web Part framework it offers, and ideas around where SharePoint could/should go. In the article he designs a realistic component and build it as a SharePoint WebPart (an Amazon search tool) then he builds the same component as an ASP.NET 2.0 WebPart. For awhile we'll have to be playing catchup as ASP.NET 2.0 comes out, then an update to SharePoint to match. In the end they'll be a convergence, just hard to see where or when that will happen so in the meantime we just struggle along our way.

  • Creating multiple lists from templates

    In the current project we're doing, we create multiple document libraries in a site when a user selects a value from a list. The choices for the list are business templates for new Contracts. A Contract can be implemented through several document libraries. Each document library makes up part of a full document that is assembled together later when the user wants to preview the whole thing. Okay, so we're golden. When we first did this we thought this would work. Iterate through all the custom list templates and build a new document library based on it. This code does that, but doesn't work:

    public void DoesNotWork()

    {

           SPSite siteCollection = new SPSite("http://localhost/sites/sitename");

           SPWeb web = siteCollection.OpenWeb();

           SPListTemplateCollection customListTemplates = siteCollection.GetCustomListTemplates(web);

     

           SPSite testSite = new SPSite("http://localhost/sites/sitename/subsite");

           SPWeb testWeb = testSite.OpenWeb();

     

           foreach (SPListTemplate spListTemplate in customListTemplates)

           {

                  string newListTitle = spListTemplate.Name;

     

                  // this fails with internal error when adding multiple lists

                  testWeb.Lists.Add(newListTitle, "", spListTemplate);

     

                  // this doesn't fix it

                  testWeb.Update();

           }

    }

     

    The problem was that we would open the target web (testWeb in the above code) and create all the document libraries we needed to based on the templates from the parent site. These were adding new document libraries based on a template, everything was valid but it would throw an exception on the second call to testWeb.Lists.Add. Even with the testWeb.Update call it still didn't help. So we had to collapse all our documents into a single one until we figured out why.

     

    After doing a couple of spike projects we found that we had to open the web each time for the multicreate to work. So this code fixed it:

     

    public void Works()

    {

           SPSite siteCollection = new SPSite("http://localhost/sites/sitename");

           SPWeb web = siteCollection.OpenWeb();

           SPListTemplateCollection customListTemplates = siteCollection.GetCustomListTemplates(web);

     

           foreach (SPListTemplate spListTemplate in customListTemplates)

           {

                  SPSite testSite = new SPSite("http://localhost/sites/sitename/subsite");

                  SPWeb testWeb = testSite.OpenWeb();

                  string newListTitle = spListTemplate.Name;

                  testWeb.Lists.Add(newListTitle, "", spListTemplate);

           }

    }

     

    Yes, you should call Dispose on the SPSite and SPWeb objects. In any case, this code works but I'm still not sure why?

  • ITPro Calgary and TechNet Winter Tour

    No SharePoint blog today but just to let you know I'll be at the TechNet Winter Tour in Calgary on March 15 (and if all works out I'll shuffle up to Edmonton for the 17th event too as MVPs are scarce up there). I'll be there wearing two hats of sorts. One as the president of the Calgary ITPro User Group and the other manning the Ask The Expert booth mainly for SharePoint technologies but I'll field questions around the technologies used on the presentation which covers Virtual Server 2005 (Great for SharePoint development setups kids), Windows Server 2003 (the core ingredient to SharePoint, see how I tie all this in?), Network Security (SharePoint has security, hey there's a pattern forming here), and Exchange Server (SharePoint, mail, alerts, you see the connection...)

    As for the Canadian ITPro User Groups, we kicked it off late last year in Calgary (along with most of the other Canadian ones) and did start the ball rolling. Now we're getting serious with a few hundred people coming out to the Mariott Hotel event. In this event, Bruce Cowper will be looking under the hood of Windows Server System. Lots of great stuff planned for this group and activities in Calgary this year.

    The venues are all filled up now but there will be more to come so stay tuned. Bruce Cowper will be presenting from Microsoft at both events and I'll be doing various stuff like serving soft drinks and running to Future Shop to buy XBox prizes or something. Watch for more Calgary ITPro User Group stuff coming shortly. Hope to see you there!

  • New Discussion Board Template

    The WSS Discussion board template is probably one of worst implementations of a threaded forum I've ever seen. Compare it to the typical Forums we see like phpBB, ASP.NET Forums, Snitz, etc. and you'll probably agree. However, finally, someone has stepped up and put together a nice alternative.

    Thanks to Serge van den Oever who brought us the Macaw SPS Joust Menu for SharePoint 2001, he's now put together the Macaw Discussion Board, a WSS template that provides last-post first views, a discussion thread view, and SWYRO (See What You Respond On).

    Great stuff! You can find the templates here for download and documentation here on his blog. Enjoy.

  • MSDN Article: Customizing List Item Forms

    A new article on of the MSDN Office Development Centre today that goes in depth around customizing forms used with List Items. Well done and informative so check it out here.

  • Looking for SharePoint Database Explorer?

    While I may be slow on the draw some people might be looking for James Edelen's excellent SharePoint Database Explorer tool. His old blog on bloggedup.com vanished (much like my portal did this morning) so he's moved sites to new blog site here. SharePoint Database Explorer is a great tool for troubleshooting SharePoint, especially if your portal is non-functioning. With just the database files you can usually restore what you need. You can get both the binaries and source to his database tool as well as SPExport here.

  • 1 is the lonliest number

    SharePoint. Some days you love it. Some days you hate it. Today is my hate day.

    Site definitions are a pretty cool thing in that you can create a whole bunch of stuff for a user without lifting a finger. In ONET.XML you can create new lists in the <Configuration> tag. So go ahead and create a bunch of document libraries like this:

    <Configurations>
    <Configuration ID="0" Name="Default
    ">
    <Lists>
    <List Title="Document Library 1" Url="Document Library 1" Type="101"/>
    <List Title="Document Library 2" Url="Document Library 2" Type="101"/>
    <List Title="Document Library 3" Url="Document Library 3" Type="101
    "/>
    <List Title="Document Library 4" Url="Document Library 4" Type="101
    "/>
    <List Title="Document Library 5" Url="Document Library 5" Type="101
    "/>
    </Lists
    >
    </Configuration>
    </Configurations>

    Great. You now have 5 brand new unique Document Libraries, all with their own paths that you can add documents into. With ONET.XML you can also add these Document Libraries to a page automatically so we do this:

    <Modules>
    <Module Name="Default" Url="" Path
    ="">
    <File Url="default.aspx" NavBarHome="True
    ">
    <View List="101" BaseViewID="0" WebPartZoneID="Footer"/>
    </File>
    </Module
    >
    </Modules>

    Awesome. Your Document Library is now smack in the Web Part Zone named Footer on your home page. Hmmm. Which document library? You only got to specify List="101". But now you're saying that you have not 1 but 5 of these things. Therein lies the rub. Just how do you get the second one on the page? And the third? Me little brain thought I would be clever and try this:

    <Modules>
    <Module Name="Default" Url="" Path
    ="">
    <File Url="default.aspx" NavBarHome="True
    ">
    <View List="101" BaseViewID="0" WebPartZoneID="Footer" Url="Document Library 1" />
    <View List="101" BaseViewID="0" WebPartZoneID="Footer" Url="Document Library 2" />
    <View List="101" BaseViewID="0" WebPartZoneID="Footer
    " Url="Document Library 3" />
    <View List="101" BaseViewID="0" WebPartZoneID="Footer
    " Url="Document Library 4" />
    <View List="101" BaseViewID="0" WebPartZoneID="Footer
    " Url="Document Library 5" />
    </
    File>
    </Module
    >
    </Modules>

    After all, each Document Library did get created and had a unique Url. Nope. This just created 5 copies of Document Library 1 on the page.

    Update: Thanks to Frans for the suggestion to change the Type in the ListTemplates section. It seems to be the only way to create multiple unique document libraries. At least you don't have to create a whole different folder under the LISTS directory and you can reuse the DOCLIB one. So basically in your ListTemplates section of ONET.XML do this:

    <ListTemplate Name="doclib" DisplayName="Document Library 1" Type="500" BaseType="1" OnQuickLaunch="TRUE" SecurityBits="11" Image="/_layouts/images/itdl.gif" DocumentTemplate="101"/>
    <ListTemplate Name="doclib" DisplayName="Document Library 2" Type="501" BaseType="1" OnQuickLaunch="TRUE" SecurityBits="11" Image="/_layouts/images/itdl.gif" DocumentTemplate="101
    "/>
    <ListTemplate Name="doclib" DisplayName="Document Library 3" Type="502" BaseType="1" OnQuickLaunch="TRUE" SecurityBits="11" Image="/_layouts/images/itdl.gif" DocumentTemplate="101
    "/>
    <ListTemplate Name="doclib" DisplayName="Document Library 4" Type="503" BaseType="1" OnQuickLaunch="TRUE" SecurityBits="11" Image="/_layouts/images/itdl.gif" DocumentTemplate="101
    "/>
    <ListTemplate Name="doclib" DisplayName="Document Library 5" Type="504" BaseType="1" OnQuickLaunch="TRUE" SecurityBits="11" Image="/_layouts/images/itdl.gif" DocumentTemplate="101"/>

    It's the Type that has to be unique, not the Name. This will allow you to put multiple document libraries onto a single page when a new site is created from your template.