How To Setup SharePoint for Visual Studio Web Projects

SharePoint makes changes to the Visual Studio configuration and applies it’s own ISAPI filter that prevent visual studio from opening web projects without some special configuration.  This document describes the process that you must do to be able to open a Visual Studio web project.

Once for the Server

The following process, which establishes a MIME type for the .tmp files that Visual Studio uses is required to be done only once for the server irrespective of the number of virtual servers that have been extended with SharePoint or the number of web applications that you want to use.

This process was extracted from the “Getting Started with Customizing a SharePoint Web Site in Visual Studio .NET” topic in the SharePoint SDK.

1)      Click the Start button, then Administrative Tools, and finally Internet Information Services (IIS).  (If you don’t have Administrative Tools on your menu you can click Control Panel.  Administrative Tools is always listed in control panel.)

2)      In the left pane expand the branches until Web Sites is showing.

3)      Right click Web Sites and select Properties from the context menu.

4)      Click the HTTP Headers tab

5)      Click the MIME Types button.

6)      Click the New button

7)      In the Extension text box type .tmp

8)      In the MIME type text box type common/type

9)      Click OK until you’re back at the main Internet Information Services (IIS) Manager console.

10)  Close the console.

Now that the server is configured for .tmp files it’s time to proceed to the steps that must be completed for each Visual Studio web project or IIS/SharePoint Virtual Server.

For Each Project

There are two basic steps that must be completed for each project: 1) Creating the exclusion in SharePoint.  2) Creating the virtual directory in IIS.  This section of the “how to” details each of these two basic operations.

Creating the Exclusion in SharePoint

By default, SharePoint handles all URLs and because of this non-SharePoint solutions on the server can not be reached.  The process of defining a managed path is detailed in a separate “how-to” document – How to Define a Managed Path Exclusion.

There must be a managed path (exclusion) for every directory that you want to use for a Visual Studio Web Project.

Creating the Virtual Directory in IIS

Now that you have created the managed path exclusions for the web projects you’re ready to create the virtual directories so that the web projects are in the same hierarchy as they occur in VSS.  This helps to reduce the number of path change-based issues that occur as files are checked in and out on different machines.  In order to get things setup correctly, follow these steps:

1)      Go to the parent directory of the project (as it is in VSS).

2)      Create a folder with the name of the web project.

3)      Click Start, then Administrative Tools, then Internet Information Services (IIS) Manager.

4)      Expand the web site that you need to add the web project to.

5)      Right click the web site, select New from the context menu and then Virtual Directory.

6)      On the welcome screen click the Next button.

7)      In the Alias text box enter the name of the virtual directory.

8)      Click the Next button.

9)      In the Path text box enter the full path for the folder you created in step 2.

10)  Click the Next button

11)  Check the Run scripts (such as ASP) checkbox.

12)  Click the Next button.

13)  Click the Finish button.

14)  Close Internet Information Services (IIS) Manager.

15)  Delete the folder you created in step 2 from the file system.

Opening the File in Visual Studio

Now that you have the folders setup all that is left is to open the solution in SharePoint and have it open the projects.  Follow these steps:

1)      Open Visual Studio and select File, Source Control, Open from Source Control.

2)      Enter the folder for the solution in the Create a new project in folder: text box provide the local path for the solution.

3)      Select the project to open in the SourceSafe project to download: tree view.

4)      Click OK.

5)      Click OK when prompted for locations for the web projects.

You have now setup a Visual Studio Web project on a SharePoint server.

How to Define a Managed Path Exclusion

SharePoint takes over all of the directories on the server so that it can create a dynamic, configuration-based, solution.  However, this creates problems when other projects or data must share the same space.  This document describes the steps necessary to create an exclusion so that non-SharePoint projects can co-exist on the same server.

Defining the Managed Path

To define the managed path follow this procedure:

  1. On the Start menu select Administrative Tools, and then SharePoint Central Administration
  2. In the Virtual Server Configuration section, click the Configure virtual server settings link.
  3. Select the virtual server that you’re interested in from the Virtual Server List.  This should be the web site that you’re going to put non-SharePoint content in.
  4. In the Virtual Server Management section, click the Define managed paths link.
  5. In the Add New Path section there is a Path text box.  In this text box, enter the path that you want to exclude.
  6. In the Type radio button list click Excluded Path.
  7. Click the OK button.
  8. Verify that the URL you selected is now listed in the Excluded Paths section.
  9. Repeat steps 5-8 for each URL you need to exclude.

You’ve now defined a managed path in SharePoint.  SharePoint will no longer try to service requests to those URLs and as a consequence the other application or content that you’ve placed in this directory should now be available.

Article: Master Advanced List Editing in SharePoint

SharePoint’s built-in tools are good at providing a basic interface for adding and editing data, however, there are times when the included editing features aren’t enough. There are applications where the SharePoint list will work, except for one small detail. For instance, you may need to ensure that one of the fields in your list matches a back-end data source. This might be accomplished by creating a drop-down that is populated from a back-end system, or perhaps it’s some custom validation that ensures that the data that the user enters is in the back-end system.

http://www.devx.com/webdev/Article/30026/

Web Services Extensions (WSE) 2.0 and SharePoint

One of my clients recently needed to have WSE installed on the same server as SharePoint.  Their policy caused some issues with SharePoint web services.  After a support call we came up with this solution to running WSE and SharePoint in the same virtual server…

1)       Create a blank policyCache.config file – or remove the nodes underneath /policyDocument/mappings and /policyDocument/policies from your existing policyCache.config file.

2)       Add to the /policyDocument/mappings node the following nodes:

 

<defaultEndpoint>

            <defaultOperation>

                        <request policy=”” />

                        <response policy=”” />

                        <fault policy=”” />

</defaultOperation>

</defaultEndpoint>

 

3)       Save the file into the C:\Program files\Common Files\Microsoft Shared\Web Server Extensions\60\ISAPI directory as policyCache.config

4)       Perform an IISRESET.

That should make WSE and SharePoint get along much better.

CAML:List @ServerTemplate

If you’re trying to work backwards from the CAML element to the SPList object…  The ServerTemplate attribute corresponds to the .BaseTemplate property.  It’s a SPListTemplateType enumeration…  The enumeration values are…

SPListTemplateType.Announcements = 104
SPListTemplateType.Contacts = 105
SPListTemplateType.CustomGrid = 120
SPListTemplateType.DataSources = 110
SPListTemplateType.DiscussionBoard = 108
SPListTemplateType.DocumentLibrary = 101
SPListTemplateType.Events = 106
SPListTemplateType.GenericList = 100
SPListTemplateType.InvalidType = -1
SPListTemplateType.IssueTracking = 1100
SPListTemplateType.Links = 103
SPListTemplateType.ListTemplateCatalog = 114
SPListTemplateType.PictureLibrary = 109
SPListTemplateType.Survey = 102
SPListTemplateType.Tasks = 107
SPListTemplateType.WebPartCatalog = 113
SPListTemplateType.WebTemplateCatalog = 111
SPListTemplateType.XMLForm = 115

 

Two more “How To” documents for SharePoint

How to customize the output of a CorasWorks Web Part

Most CorasWorks’ web parts have a hidden property called Display which can be added to the DWP file which will change the basic display behavior of the web part so that it emits the specific output that you’re looking for.  Because the display tag is hidden it’s not available from the tool pane and must be added to the DWP file directly.

 

Exporting the DWP

The first step is to configure the CorasWorks component so that it is correctly returning the right data and export that web part as a DWP so there will be a file that is correctly configured.  To do this, make sure that the title bar for the web part is shown.  If the title bar isn’t shown, enter Design mode by clicking on Modify Shared PageDesign this Page. Next, click the down arrow on the right hand side of the web part title bar.  On the context menu select Export…, save the file when prompted.

Creating the Content

The next step to customizing the output is to create the format for the replacement.  The basic format for the replacement is a set of HTML fragments each terminated with a <END> "tag".  The orders of these elements is header, item (non-selected), footer, and (when appropriate) a final section for selected items.  The Special Site Navigation component is the only component which has a section for selected items at this point.

 

In each of these sections there are several replacement strings which will be replaced with the value contained in the associated field or property.  An example of the content to make a spreadsheet roll up look like a linked list appears below:

 

<!–Header//–>

<table border="0" width="100%">

<END>

<!–Body//–>

<tr><td style="padding-bottom: 5px" class="ms-vb"><img src="/_layouts/images/square.gif"></td><td style="padding-bottom: 5px" class="ms-vb"><a HREF="<%Link%>"><%Display%></a></td></tr>

<END>

<!–Footer//–>

</table>

<END>

 

Known Replacement Strings

For a list the replacement strings are the field names surrounded by a <% and %>.  You can see this in the above example of <%Link%> and <%Display%> — these are both fields in the lists being rolled up by CorasWorks’ web part.

 

For special site navigation, there are only three replacement strings that are valid:

 

  • PageURL –  The Url of the page to link to.  This value comes from the underlying navigation list.
  • PageTitle – The text to display for the page.  In other words, the friendly name for the page. This value comes from the underlying navigation list.
  • Target – The target to open the window in, from the web part properties.

 

Adding the Tag

Adding the tag to the XML is simple, but is very specific.  First, the value must be encoded or placed in a CDATA section so that it is not interpreted as a part of the XML.  The best way to do this is the CDATA section so the Display property will still be readable.

 

First, add a new <Display></Display> tag set prior to the closing </WebPart> tag in the DWP file.  Next copy the xmlns attribute from the last tag prior to the new display tag you just added and add that attribute to the display tag.  Each web part uses it’s namespace for the Display tag.  You must provide this xmlns attribute for the Display node or it will not work.

 

In the middle of the <Display></Display> tag set add a CDATA node by adding <![CDATA[ ]]>.  In the middle of the two brackets ‘[ ]’ add the content that you created above.

 

Save the DWP file.

 

Trying the modified file

The next step is to import the modified DWP file.  From the Modify Shared Page menu select Add Web Parts and Import.  Click the browse button and locate the DWP file that you modified.  Click the Upload button to upload the control.  Drag the control on to the page from the tool pane.

 

The display of the links or navigation should reflect the updated HTML that you provided.

 

Troubleshooting

 

If for some reason you don’t see any modified display make sure that your <Display> tag has the correct xmlns attribute.  It should match the other xmlns attributes in the file.

How to Add a Reference to an Assembly in a Web Part

Adding a reference to a shared library from a web part is not as simple as using visual studio to add a reference to a project output or a fixed DLL on the file system.  In addition to adding the reference to the project itself, you must add the DLL to the cab file and modify the manifest.xml so that the referenced DLL is deployed with the web part.  This How To shows you what must be done for the web part to deploy correctly when referencing another assembly.

 

Adding the reference to the project

Adding the reference to the project can be done with the following steps:

 

  1. Right Click References under the web part project and click Add Reference…
  2. Click the Projects tab.
  3. Click the project and click Select or double-click the project so that the project appears in the Selected Components list at the bottom of the dialog.
  4. Click the OK button.

 

Now you have added the reference to the project.  Next is adding the DLL to the CAB file.

 

Adding the Referenced DLL to the CAB file

The process of adding the referenced DLL to the CAB file is easy.  Simply follow these steps:

 

  1. Right click the setup (CAB) project, select Add from the context menu, and finally Project Output…
  2. Select the correct project for the output file in the Project drop down at the top of the dialog.
  3. Click the Primay output item in the list.
  4. Click the OK button.

 

Now that you’ve added the DLL to the Cab file it’s time to add the file to the manifest.xml.

 

Adding the Reference to Manifest.xml

The final step is to add the file to manifest.xml so that STSADM will deploy the DLL for you when the web part is deployed.  You can do this by following these steps:

 

  1. Open the manifest.xml file for the web part project in Visual Studio
  2. Locate the </Assemblies> tag.
  3. Add a new tag <Assembly FileName="" /> immediately before the </Assemblies> tag
  4. Add the name of the referenced DLL to the FileName attribute of the <Assembly> tag that you just added.  Note that the name should not include any path information.  It should be the complete name of the referenced DLL—including the DLL extension.
  5. Safe the file.

 

Now you have completed the changes necessary for the web part project to deploy the referenced DLL along with your web part.

CAML can take a long walk across the desert…

Back in March I attended a MS Book Publishers Summit in Redmond.  I had the pleasure to sit down with Mike Fitzmaurice.  What came out of his blog entry “CAML is Here to Stay“.  I was the mysterious “guy” mentioned in the post.

Fitz’s post was reassuring – sort of .  It told me that there would be some support for CAML and that there was hope for all of us struggling with the poor (ok, missing) documentation on CAML and how it works.  I was encouraged because I knew how much of SharePoint requires CAML and how not knowing the rules for CAML hampers your ability to do anything in SharePoint – from queries to site definitions you’ll find so much CAML you’ll swear you’re in a desert.  (Sorry, I had to get that one in.)

However, despite Fitz’s claims we still struggle to find good documentation on CAML.  Every new bit of information on the topic seems to lead to more that remains undocumented.

The reason for this post is to make public one of the recent interactions that I had with the product support group – and the response I got.  I think it illustrates the problems that I have with CAML – the challenges that I think all of us face.

I’ve got a set of utilities that allow you to migrate configuration data (web part placement, lists, etc.) from one site to another.  (The utilities are not unlike the Echo utility from WinAppTechnology.) They rely upon the SharePoint object model to function because frankly they have to – not everything is exposed through the web services (Please make everything available via web services.) or the FrontPage RPCs (Please kill these off.)  However, the problem with this is that it limits their ability to be used to a single configuration database.  In other words, I can’t push configuration from development to staging.  I’ve got a work around in creating a backup of a site in development, restoring it in staging, and using that as my template for changes.

This is difficult to do and requires manual intervention.  The possibility for errors is fairly large.  This approach doesn’t fly very well when you have a tightly controlled production environment – which most customers have.  It ends up being a big issue.

So my current client and I found out that the template file (user site template – STP) is really a renamed cab file with a manifest.xml file in it.  Manifest.Xml is CAML.  So the thinking was that this would have what was necessary. To replicate the site.  If the template can create a site surely it has all of the data about the site and should therefore be possible to use as a starting point to make updates.

Having this XML based serialization of the site means that we can pack up the file and use it as a template on another server.  This means that we could have a very clean implementation for deploying from environment to environment.  We started down the process of implementing this mechanism believing that we were well within guidelines.  We weren’t touching the database – we were using a file that is in a supported format.  Everything should be fine.

Well, that’s a good idea, but unfortunately, the word back from the development team is that they don’t want to support people using the manifest.xml file in an STP.  At least they don’t want to support the areas of that file which are not documented CAML.  They have a binary serialization of web parts in the file which they’re not planning on sharing the details to.  The net effect is that it’s not possible to get web parts from an STP files Manifest.xml

That leaves me with very few options.  Officially, I can’t use the data in a solution so I’d have to come up with my own mechanism for serializing this data – integrating that into the manifest.xml file and shipping that around.  Of course, if I modify the schema to ship the web parts around I’m no longer moving CAML so there’s no telling if I’ll be able to use that data anyplace except in my application.

I’ve not yet figured out how to resolve the issue – however, I’m looking for input here.  Am I the only one that thinks that if Microsoft says they’re going to support CAML that they should support it every time they write it out?  Am I the only one who sees that this kind of “We’re supporting it” and then when we go to actually use it we get “That’s not supported” is making life really difficult?

Thoughts?

Creating a new set of list items from one list into another

Here’s the other bit of code having to do with the pesky created/modified dates.  This is just a function and not a whole program.  It deletes all of the items in a destination list and then copies all of the items from the source list.  The interesting bit is that the created/modified fields hold up to this mechanism.  You can create a new list item that maintains the created/modified dates of the original item.  As with the previous code — this is not intended for direct use.  It’s designed to show you how you might copy the created/modified fields from one list to another.

  /// <summary>
  /// Copy list data from one list to another
  /// </summary>
  /// <param name="spListRef">The source of the list data</param>
  /// <param name="spListTarget">The target (destination) of the list data</param>
  public static void CopyListData(SPList spListRef, SPList spListTarget)
  {
   if (spListRef.BaseType == SPBaseType.DocumentLibrary)
   {
    CopyDocumentData(spListRef, spListTarget);
    return;
   }
   SPListItem spListItemTarget;

   // Delete all Items
   while (spListTarget.Items.Count > 0)
   {
    spListTarget.Items.Delete(0);
   }

   foreach(SPListItem spListItemRef in spListRef.Items)
   {
    spListItemTarget = spListTarget.Items.Add();
    foreach(SPField spFieldRef in spListItemRef.Fields)
    {
     if (spFieldRef.Type != SPFieldType.Attachments &&
      spFieldRef.Type != SPFieldType.Calculated &&
      spFieldRef.Type != SPFieldType.Computed &&
      spFieldRef.Type != SPFieldType.Counter &&
      spFieldRef.Type != SPFieldType.CrossProjectLink &&
      spFieldRef.Type != SPFieldType.Error &&
      spFieldRef.Type != SPFieldType.File &&
      spFieldRef.Type != SPFieldType.Invalid &&
      spFieldRef.InternalName != "owshiddenversion" &&
      spFieldRef.InternalName != "InstanceID" &&
      spFieldRef.InternalName != "Order" &&
      spFieldRef.InternalName != "GUID"
      )
     {
      spListItemTarget[spFieldRef.InternalName] = spListItemRef[spFieldRef.InternalName];
     }
    }

    foreach(string attachmentUrl in spListItemRef.Attachments)
    {
     string fullUrl = string.Format("Lists/{0}/Attachments/{1}/{2}", spListRef.Title, spListItemRef.ID,
                                 attachmentUrl);
     SPFile srcAttach = spListRef.ParentWeb.GetFile(fullUrl);
     spListItemTarget.Attachments.Add(attachmentUrl, srcAttach.OpenBinary());
    }
    spListItemTarget.Update();
   }
  }