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?

2 Comments

  • The SP collection classes are derived from a class called SPBaseCollection because the are not the normal run of the mill collections...they make SQL server calls to the configuration and content databases. Everytime you use code like this:



    testWeb.Lists.Add(..)



    you are not using the same object because the SQL call is done again...hence it runs the first time but not the second.



    So to fix this in your origional code you can do something like this:



    prior to the foreach loop do this:

    SPListCollection lcol = testWeb.Lists;



    then in the loop do this:



    lcol.Add(...)





    I was doing some programming using the SP object model and found this piece of advice. It had to do with the difference between using the object model to do my own windows forms admin application versus using MS SP web services. They said their web services were optimized and gave this type of behaviour as an example of how to program using the SP objects.



  • I wanted to say that I tried all of the other solutions out there and none of them worked as expected. Using the snippet that you provided, I am able to access a survey on my site anonymously! Thanks so much.

Comments have been disabled for this content.