Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Fear and Loathing

Gonzo blogging from the Annie Leibovitz of the software development world.

  • Managing Virtual PC Images with SharePoint Development

    I have a lot of Virtual PC images. A lot. Like 20+ just for SharePoint development alone. It seems excessive, but there are a lot of configurations I need to suport (https vs anonymous vs workgroup) as well as various sites we host at work (several SharePoint based applications, a few portals and a couple of Enterprise portals in development for 2005/06). On top of that, I have a few setups that are the SharePoint 2003 / Visual Studio 2005 experiments (which are pretty ugly at this point). Managing all these images is a bit of an issue and even at 5-10gb per image, a 200gb drive fills up pretty quick.

    I stumbled across a nice post by Jan Tielens on Virtual PC images and differencing. Something I hadn't done before as all my images are built from scratch. This is not only time consuming in the construction (and something a trained monkey or a well-written NAnt script could do) but they're time consuming to copy around when you need something "almost" like that image but not quite. There is a nice walkthrough blog here on Matt Hausmann's site that gives you a nice visual guide on building difference images.

    So after spending a dozen hours or so butchering my SharePoint images, I've reduced my VPC files from 180gb down to 25gb with the same number of images. Pretty slick and creating a new one takes about a minute. I highly recommend you take a look at this for your own VPC image management if space or time is a concern. Now onto my Visual Studio images. Sigh.

    Okay, so this post wasn't really a HOWTO on managing Virtual PC images but hey, it's something to blog about.

  • SharePoint Code Camp

    I recently stumbled over Thom Robbins .NET Weblog (now a new place I visit on a regular basis) and found a cool idea called Code Camp! Code Camp is where you get as many developers together as you can and, well, code. It's somewhat of a new concept (new to me anyways) but really looks like it rocks and has somewhat of an open source quality to it (all code is free and openly shared with everyone). Best of all, it's FREE! The "official" Code Camps are composed of hundreds of developers and there's one coming up in February. Check out the MSDN Code Camp site for more info (although it's pretty slim on details right now). Additionally, Thom published what he calls the Code Camp Manifesto which puts together some simple protocols to follow.

    Anyways, the idea really interests me and will be a blast so I'm going to look at organizing a SharePoint Code Camp. On the off-chance I can't get enough raw SharePoint developers (which may not be surprising), I'll look at doing a more general .NET/Web Services Code Camp (perhaps talking to SharePoint, have to get it mixed in there somewhere). I'll hit up the local RD John Bristowe and my MSDN contacts to get something happening in Western Canada for the new year.

    As Code Camp content is determined by the community I'll be looking to you to contribute. So come by, learn, teach, have fun, whatever. Let me know if you're interested in attending, participating, helping, etc. and we'll see what we can shake up.

  • Consuming Web Services with SharePoint

    Merry Christmas! Hope you and yours are having a happy holidays.

    I've been working a lot with consuming web services and DataView Web Parts (DVWP) with SharePoint lately. FrontPage 2003 lets you create these very cool things called DataView Web Parts. Basically they consume a web service (either one your write or something someone can provide) and expose the results as a webpart that you can use/re-use on your SharePoint site. With the magic of XSLT you can get the results looking grand.

    This example walks you through consuming a web service from the Microsoft Money site and get live stock quotes (well, 20 minute delay anyways) all without a stitch of code. Okay, no C# written here but some people will say that coding XSLT is pretty much the same as writing code. You be the judge however the example here was to get a single stock quote web part consuming an external web service, all without having to break out your Visual Studio.NET toolkit.

    First we'll need a page to add the DVWP to. This can be your default.aspx page but I prefer to create a new webpart page, stick it into a document library and edit the page from there. That way I'm not un-ghosting my default.aspx page and I can delete the doclib later and not use it in production. Either way, your choice.

    1. Load the page up into FP2003
    2. Select (or create) a Web Part Zone
    3. Select Data | Insert Data View from the menubar
    4. Expand the XML Web Services Data Source from the Task Pane
    5. Select Add to Catalog...
    6. Enter http://office.microsoft.com/Research/Providers/MoneyCentral.asmx?WSDL the Service description location. This is the URL to the Microsoft Money Web Service.
    7. Select Connect Now. This will populate the rest of the dialog with the available services
    8. Select MoneyCentralRemoteSoap from the dropdown list
    9. Select DDSQuery from the Operation list
    10. Double click on symbol in the Parameters list
    11. Enter your stock symbol in the Value field (for this post I used Canadian Pacific Railway which is "CA:CP" but you can use any valid symbol like MSFT for Microsoft, YHOO for Yahoo, etc.)
    12. Select the checkbox so you can enter this value at runtime.
    13. Double click on language in the Parameters list
    14. Enter en-US as a value here (English/United States, you can enter other values here for other languages)
    15. Click OK

    This will add a new Data Source into your catalog called MoneyCentralRemote on office.microsoft.com. You can now drag and drop this data source onto a Web Part Zone. Once you do this your web part will look like this:

    DDSQueryResult <StockData xmlns:dt="urn:schemas-microsoft-com:datatypes"><Quotes><Quote Symbol="CA:CP"><Last dt:dt="float">40.98</Last><LastTime dt:dt="string">10:05 AM</LastTime><LastSize dt:dt="float">100.00</LastSize><Ask dt:dt="float">40.98</Ask><Bid dt:dt="float">40.90</Bid><Open dt:dt="float">41.00</Open><Close dt:dt="float">40.80</Close><High dt:dt="float">41.00</High><Low dt:dt="float">40.61</Low><Volume dt:dt="float">20,172</Volume><Change dt:dt="float">0.18</Change><PercentChange dt:dt="float">0.44</PercentChange><EPS dt:dt="float">2.87</EPS><PE dt:dt="float">14.28</PE><SharesOut dt:dt="float">100.00</SharesOut><Currency dt:dt="string">CAD</Currency><Exchange dt:dt="string">Toronto</Exchange><Type dt:dt="string">Equity</Type><CompanyName dt:dt="string"><![CDATA[CANADIAN PACIFIC]]></CompanyName></Quote></Quotes><Attributions><Timing><![CDATA[Quotes delayed at least 20 min]]></Timing><Attribution priority="1"><![CDATA[<a href="http://www.comstock-interactivedata.com"><img border="0" align="absmiddle" src="http://office.microsoft.com/Research/Images/splgo.gif" /></a> Quotes supplied by <a href="http://www.comstock-interactivedata.com">Standard & Poor's ComStock, Inc.</a>]]></Attribution><Attribution priority="1"><![CDATA[<a href="http://moneycentral.msn.com/investor/partsub/funds/mstar.asp"><img border="0" align="absmiddle" src="http://office.microsoft.com/Research/Images/mornlgo.gif" /></a> Fund data provided by <a href="http://moneycentral.msn.com/investor/partsub/funds/mstar.asp">Morningstar, Inc.</a>]]></Attribution><Attribution priority="2"><![CDATA[<a href="http://privacy.msn.com/tou">Terms of Use</a>]]></Attribution></Attributions><Warning>NoWarning</Warning></StockData>

    Now you'll want to let your users enter a stock symbol and the web part will do the lookup based on that value. Do this from inside FP2003 (I find you can't always perform a connection between a DVWP and another web part in the browser)

    1. Click on a zone and select Insert Web Part
    2. From the Task Pane select the Form Web Part and add it to the page
    3. Right click the Form Web Part in FP2003 and select Web Part Connections... from the popup menu
    4. Select Provide Form Values To in the action dropdown and click Next
    5. Select Connect to a Web Part on this page and click Next
    6. Choose the DVWP in the Target Web Part dropdown
    7. Choose Modify View Using Parameters From in the Target Action dropdown
    8. Select the column next to symbol (should be the second one) and select T1 as the dropdown value. T1 is the default name for the input field on the Form Web Part.
    9. Click Next then Finish to complete the connection

    You now have a connection from the Form Web Part to your DVWP. When a user enters a stock symbol in the Form Web Part and clicks on Go, the information is fed to the DVWP (mapping the value in T1 from the Form Web Part to the symbol parameter in the DVWP). This will re-invoke the webservice behind the DVWP with the symbol value updated and return the result.

    That's it! Live stock quotes from the Internet on your WSS/SPS site (this works with both) all without a single line of code. My XSLT knowledge is abysmal (read:none) so you'll have to bear with me on the formatting of the results here but I'm some of you are crafty enough to work with this. You'll probably want to format the XSLT so it displays something like this maybe:

    Symbol MSFT
    Last 27.01
    Change +0.04
    % Change +0.15%
    Volume 65.82 Mil
    Day's High 27.15
    Day's Low 26.83

    Or whatever works for you. Just do a match on the XML so you find the Last, Change, Volume, etc. nodes and make it pretty. (and if someone wants to email me a xsd file I'll update this post and probably learn about XSLT a little). In my effort to try to achieve this look from the XML returned from the web service, it keeps coming out the same. One big XML dump. Sigh.

    Hope that gets you started using Web Services with FP2003 and SharePoint. I'm sure you'll have other uses that make sense to you as this is just an example.

  • Corporate Branding with SPS

    I gotta love the web. Somehow, somewhere, you'll be taken to corners of the web you've never seen before and find little gems of information that otherwise you might stumble across someday if you get the right sequence of keywords pumped into Google. Thanks to Chris Johnson's blog I was pointed to 2 new documents on Corporate Branding with SPS. I've been doing a lot of customization work in SharePoint lately as we're building some apps (like a new contract management system) right into the application. Some of things we've done is pretty cool (like making it look like no matter where you are, WSS or SPS, you always see the same navigation metaphor).

    So here's two Office Development articles on branding your SPS site with some great examples and ideas (like being able to add new buttons to the action area that I didn't know before). Hope it helps you:

    Part 1, Understanding the Use of the Corporate Brand
    Part 2, How to Apply your Corporate Brand

  • Applying Permissions to Lists in Areas

    A nice feature of SharePoint Portal Server are areas. Think of an area as a mini-WSS site of it's own. You can create document libraries, custom lists, discussion threads, etc. all within an area. Items in the portal, including entire areas, have the added advantage over WSS sites of being able to use audience filtering and thereby only show content to those that it's aimed for (remember audience filtering is just what's presented, you still need to apply appropriate security to deny access to something to someone).

    Security for areas is the same as you would apply security anywhere else in SharePoint. You can add new users, change permissions, etc. (although when you select the advanced permissions for an area you get more options like being able to apply stylesheets, browsing directories, etc.) One of the issues security in an area is that if you have say several document libraries in that area, the security is the same for all libraries.

    When you select a list or document library (through the Manage Content option) in SPS, you'll see the typical interface like Change general settings, Delete this list, etc. What you won't see is the option that you see when you go into the settings in a list or library in a WSS site. Namely the Change permissions for this list option. When you apply permissions to an area (using the Manage Security option), you'll see the typical SharePoint interface to add users, etc. but no option to set permissions for a list or library. You can however still use a feature of SharePoint to apply individual permissions to a document library or list in the area, it just takes a little typing to get there.

    If you hover over the Change permissions for this list option in a WSS site, you'll see a url similar to the following:

    http://servername/sites/sitename/_layouts/1033/ShrOpt.aspx?obj={1234567A-BBBB-C999D9999999},list

    This is the page where you can set permissions for a list or document library (for document libraries, the end of the url will say ",doclib" instead of ",list"). The page exists in a virtual directory that's available to any WSS site and... portal area! This same url format can be used for an individual document library or list at the portal. You just need to know the GUID (the 1234567A number above). To find this out:

    1. Select Manage Content from there area where your document library or list lives in the portal
    2. Select the document library or list from the ones available
    3. Select Modify settings and columns for that list
    4. Take a look at the url you've gone to. You'll see listedit.aspx?List={... The numbers between the {} characters is the GUID for that list. The easiest way to get from this page to the ShrOpt page is to change the URL from this:
      http://servername/_layouts/1033/listedit.aspx?List={30BDBE4A-829A-4FD1-A237-D1D3D60EFF02}
      to this:
      http://servername/_layouts/1033/ShrOpt.aspx?obj={30BDBE4A-829A-4FD1-A237-D1D3D60EFF02},list
    5. Now you'll be at the Change Permissions: Document Library (or list) page
    6. Modify the permissions as you normally would, adding or removing users and setting up permissions.

    These permissions will only be applied to the document library and not to the entire area so you can now create read-only areas with editable lists. Enjoy!

  • Creating custom pages in SharePoint

    One of the really cool things about SharePoint is that you can create your own custom aspx pages like you would any ASP.NET application, but with a few tips you can leverage all the features of SharePoint like using web part zones and allowing customization and personalization.

    When creating a custom page be sure to inherit from WebPartPage. Here is how you get the navigation on your own page.

    1. Inherit from the WebPartPage class in your new webpage:

    <%@ Page language="C#" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,
    Microsoft.SharePoint,Version=11.0.0.0,
    Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>

    2. Create references to required tag libraries

    <%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

    3. Apply Theme server control

    <SHAREPOINT:THEME id="Theme1" runat="server"></SHAREPOINT:THEME>

    4. Add CSS Link server control

    <SharePoint:CssLink DefaultUrl="/_layouts/1033/styles/ows.css" runat="server" ID="Csslink2" />

    5. Add client-side script links

    <script src="_layouts/1033/owsbrows.js"></script>
    <script src="_layouts/1033/ows.js"></script>

    6. Create table and add navigation server controls

    <TABLE class="ms-main" CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%" HEIGHT="100%">
    <!-- Banner -->
    <TR valign="top">
    <TD COLSPAN="3" WIDTH="100%">
    <!--Top bar-->
    <table class="ms-bannerframe" border="0" cellspacing="0"
    cellpadding="0" width="100%">
    <tr>
    <td nowrap valign="middle"><img ID="onetidHeadbnnr0"
    alt="Logo" src="/_layouts/images/logo.gif"></td>
    <td class="ms-banner" width="99%" nowrap ID="HBN100"
    valign="middle">
    <!--webbot Bot="Navigation" startspan-->
    <SharePoint:Navigation LinkBarId="1002" runat="server" ID="Navigation1" />
    </td>
    <td class="ms-banner">&nbsp;&nbsp;</td>
    <td nowrap class="ms-banner" style="PADDING-RIGHT: 7px">
    <SharePoint:PortalConnection runat="server" ID="Portalconnection1" />
    </td>
    </tr>
    </table>
    </TD>
    </TR>
    </TABLE>

    That's it! Once you've done this your page is "SharePoint" ready. You can define web part zones (using FrontPage 2003) for your web designers and developers to add new webparts to for customization and personalization. Enjoy!

  • Syncronization of Office Document Properties with WSS Document Libraries

    I've been spending a lot of time with Office and syncronizing properties with WSS document libraries I thought I would share. There are a few sources out there like the WSS FAQ section on Office Interaction but I thought I would try to get into some more detail here as there are some dos and donts and gotchas along the way.

    Concept

    When you upload a document through one of several ways, properties from the document will transfer to SharePoint fields automagically. This assumes you've actually setup the fields in WSS (only the Title property is created by default). There are four ways to upload a document to a SharePoint document library where this works:

    1. Copy and paste the document into Explorer View
    2. Drag and drop a document via a mapped drive (Windows XP only) or through your Network Places folder
    3. Save the document directly from Word/PPT/Excel into a WSS document library.
    4. Upload multiple files via the Office 2003 capability

    The last two options require Office 2003 (although you can save from Office 2000 and XP it doesn't always work properly as WebDAV is a little kludgy)

    Uploading the document through the "Upload Document" option on the toolbar for the document library is a Upload->Set Properties excercise. In other words, you have to upload the document (by picking it via the Browse button) then set the properties. When you select a file from your system to upload, the properties are not automatically set (although I feel they should be so hopefully we'll see this in a future version or service pack). Using the "Upload Multiple Files" gets around this problem, but again requires an Office 2003 client.

    Built-in Properties

    Word, Office, Powerpoint and Excel (and maybe OneNote and the other "core" products) have a set of default file properties. You can set these programatically (through COM automation) or via the File | Properties menu. These properties are:

    • Subject
    • Author
    • Manager
    • Company
    • Category
    • Keywords
    • Comments
    • Hyperlink base

    These properties do not transfer to a SharePoint document library (again, I think a failing of WSS and should be fixed).

    Note: There is something deep in the central administration screens that talk about mapping Office DAV properties so I'm still looking into how this works and maybe to overcome this problem.

    Custom Properties - Microsoft

    In addition to the built-in properties, Microsoft creates by default a series of custom properties. These are accessible via the File | Properties menu on the Custom tab. By default they're all blank but you can choose to set any of them. These are named:

    • Checked By
    • Client
    • Date completed
    • Department
    • Destination
    • Disposition
    • Division
    • Document Number
    • Editor
    • Forward To
    • Group
    • Language
    • Mailstop
    • Matter
    • Office
    • Owner
    • Project
    • Publisher
    • Purpose
    • Received from
    • Recorded by
    • Recorded date
    • Reference
    • Source
    • Status
    • Telephone number
    • Typist

    Creating a field in the WSS document library with the same name as these will result in a transfer (if the property is set in the document and you use one of the four ways to upload the document). Note that once you create a field, it has an internal name (like Status) but you can change it after the fact. It will always have that internal name and if that name maps to a property, it stays that way no matter what name you change it to.

    Custom Properties - Yours

    Just like the default custom properties that Microsoft creates, there's no stopping you from adding any custom property. Just type in the name in the File | Properties custom tab and click Add. This will add a new property like "Creator" or something. You'll still have to set this but if you do, it will transfer to WSS (again if you create the field in the document library to match).

    Transfering

    As mentioned in this blog, properties set in Office documents will transfer to a WSS document library as long as two conditions are met:

    1. The property is set in the document itself as a text custom property
    2. The field is created in the WSS document library as a text field

    Custom Properties - Lookups

    One of the nice things about having meta-data for your documents in WSS is that you can control the properties and lookup values. Lookup tables are great for this but there's a problem with properties and transfering using a lookup. It doesn't work. Say you have a field called "Status" (one of the default custom properties) and set it "Draft" in the document. Status is a lookup into another SharePoint list you created where the user can set the value. When you transfer the document to WSS, the property doesn't get set.

    However if your "Status" field in WSS is a choice field with the values you want AND you have the document property set to something that matches, the transfer works correctly. WSS doesn't care you have a custom property called "Status" in your document with a value of "Fixed" but the choices in WSS are only "Draft" and "Final". It will gleefully set the value to "Fixed" but when you edit the properties, since WSS can't find "Fixed" in the list of choices, it'll revert back to nothing (or the default value if this is a mandatory field).

    So basically, if you want to have a picklist for your lookups and syncronize those values from Office -> WSS and back again:

    1. Ensure the WSS field type is "Choice" with a set of values (multi-choice through checkboxes does not syncronize)
    2. Ensure the property in Office is a text value and matches one of the choices in the WSS document library

    Value Types

    Office documents let you create 4 different value types for custom properties. Synchronziation (and the field type) in WSS must be text only and the type in the office document must be the same so store all custom properties in your office documents as Text fields in order to ensure synchronization.

    Syncronization

    As for keeping things in sync, if you set the property in WSS it will transfer to the document so when you open it and look at the File | Properties | Custom tab they'll be updated. If you set it in the document it will tranfser using one of the four methods described above. If you save a single document directly into the document library, it will clear out the file property and ask you for the value.

    Summary

    In conclusion, it's a powerful feature to synchronize (and populate) SharePoint document libraries with properties from Office documents. Imagine if you had a document library with all kinds of views using meta-data and you had a massive amount of documents with these properties set. A simple drag-n-drop operation into your document library and now all your views are ready to go. Even with issues around syncronization and non-existent built-in properties, it's a useful feature to leverage in your solutions.

    Other References

    WSS FAQ - Interaction with Office
    WSS FAQ - Syncronization Issues with Certain Properties

  • Removing Large Document Libraries

    Haven't been blogging much as I've been burning the candle at both ends (and sometimes all three ends) trying to get wrapped up for 2004 and ready for 2005 at work (not an easy task). I did have a tip that I came across though that I thought I would share.

    If you have a very large document library or list (either one with a lot of folders/documents or one with very large documents) you may find if you try to go and delete the library/list from the settings page that it fails (with a very cryptic message to contact your server administrator). The easy solution is to jump into Explorer view (yes, I hate it as much as you do) and delete files and folders from there, not grabbing too many at once. Basically I found that deleting 30 or 40 folders/files at once to be a good number. Sure, it can take awhile and you can experiment on increasing that number but I suggest you don't try selecting all 1000 files at once and deleting them. If you don't have Explorer View (personally I delete them on all my document library until Microsoft fixes the version bug with them) then just use your Network Places (or a mapped drive under XP) to get to the site and delete from there. For some reason when you delete the entire library from the admin screen, it sometimes chokes so this is a way around it. Your mileage may vary.

  • Your very own Quick Launch

    A question that gets asked often is about the Quick Launch menu in WSS sites. Whenever you create a list or document library, one of the options is to show it on the Quick Launch. This places it into a grouped category under Documents, Pictures, Lists, etc. It's very effective for directing your users to the content of the site. There are however sometimes where you want to control what you display here and in some cases, users get confused over seeing a heading called Surveys but none to be found. A simple fix is to load the page up in FrontPage and remove those sections. However here's a tip that makes it more flexible (yes, you'll still need to do this in FrontPage but only once).

    The whole Quick Launch area is just a simple table made up of Navigation webbots and headings. Rather than having tables for our Quick Launch let's replace it with a new Web Part Zone. This way we can allow web developers (and/or people with the appropriate rights) to add web parts to this section rather than having them load up FrontPage to do any customization.

    The table in question starts at line 118 of default.aspx. You can select it in design mode and either delete it or just clear out the contents (I suggest highlighting the contents and deleting it, leaving an empty table).

    So this gobbly-gook:

    <TD class="ms-navheader"><A HREF="_layouts/1033/viewlsts.aspx?BaseType=1">
      Documents</A></TD></TR>
        <TR><TD style="height: 6px">
      <!--webbot bot="Navigation" S-Btn-Nobr="FALSE" S-Type="sequence" S-Rendering="html" S-Orientation="Vertical" B-Include-Home="FALSE" B-Include-Up="FALSE" U-Page="sid:1004" S-Bar-Pfx="<table border=0 cellpadding=4 cellspacing=0>" S-Bar-Sfx="</table>" S-Btn-Nml="<tr><td><table border=0 cellpadding=0 cellspacing=0><tr><td><img src='_layouts/images/blank.gif' ID='100' alt='Icon' border=0>&amp;nbsp;</td><td valign=top><a ID=onetleftnavbar#LABEL_ID# href='#URL#'>#LABEL#</td></tr></table></td></tr>" S-Target TAG="BODY" --></TD></TR>
        <TR><TD class="ms-navheader"><A HREF="_layouts/1033/viewlsts.aspx?BaseType=1&ListTemplate=109">
      Pictures</A></TD></TR>
        <TR><TD style="height: 6px">
      <!--webbot bot="Navigation" S-Btn-Nobr="FALSE" S-Type="sequence" S-Rendering="html" S-Orientation="Vertical" B-Include-Home="FALSE" B-Include-Up="FALSE" U-Page="sid:1005" S-Bar-Pfx="<table border=0 cellpadding=4 cellspacing=0>" S-Bar-Sfx="</table>" S-Btn-Nml="<tr><td><table border=0 cellpadding=0 cellspacing=0><tr><td><img src='_layouts/images/blank.gif' ID='100' alt='Icon' border=0>&amp;nbsp;</td><td valign=top><a ID=onetleftnavbar#LABEL_ID# href='#URL#'>#LABEL#</td></tr></table></td></tr>" S-Target TAG="BODY" --></TD></TR>
        <TR><TD class="ms-navheader"><A HREF="_layouts/1033/viewlsts.aspx?BaseType=0">
      Lists</A></TD></TR>
        <TR><TD style="height: 6px">
      <!--webbot bot="Navigation" S-Btn-Nobr="FALSE" S-Type="sequence" S-Rendering="html" S-Orientation="Vertical" B-Include-Home="FALSE" B-Include-Up="FALSE" U-Page="sid:1003" S-Bar-Pfx="<table border=0 cellpadding=4 cellspacing=0>" S-Bar-Sfx="</table>" S-Btn-Nml="<tr><td><table border=0 cellpadding=0 cellspacing=0><tr><td><img src='_layouts/images/blank.gif' ID='100' alt='Icon' border=0>&amp;nbsp;</td><td valign=top><a ID=onetleftnavbar#LABEL_ID# href='#URL#'>#LABEL#</td></tr></table></td></tr>" S-Target TAG="BODY" --></TD></TR>
        <TR><TD class="ms-navheader"><A HREF="_layouts/1033/viewlsts.aspx?BaseType=3">
      Discussions</A></TD></TR>
        <TR><TD style="height: 6px">
      <!--webbot bot="Navigation" S-Btn-Nobr="FALSE" S-Type="sequence" S-Rendering="html" S-Orientation="Vertical" B-Include-Home="FALSE" B-Include-Up="FALSE" U-Page="sid:1006" S-Bar-Pfx="<table border=0 cellpadding=4 cellspacing=0>" S-Bar-Sfx="</table>" S-Btn-Nml="<tr><td><table border=0 cellpadding=0 cellspacing=0><tr><td><img src='_layouts/images/blank.gif' ID='100' alt='Icon' border=0>&amp;nbsp;</td><td valign=top><a ID=onetleftnavbar#LABEL_ID# href='#URL#'>#LABEL#</td></tr></table></td></tr>" S-Target TAG="BODY" --></TD></TR>
        <TR><TD class="ms-navheader"><A HREF="_layouts/1033/viewlsts.aspx?BaseType=4">
      Surveys</A></TD></TR>
        <TR><TD style="height: 6px">
      <!--webbot bot="Navigation" S-Btn-Nobr="FALSE" S-Type="sequence" S-Rendering="html" S-Orientation="Vertical" B-Include-Home="FALSE" B-Include-Up="FALSE" U-Page="sid:1007" S-Bar-Pfx="<table border=0 cellpadding=4 cellspacing=0>" S-Bar-Sfx="</table>" S-Btn-Nml="<tr><td><table border=0 cellpadding=0 cellspacing=0><tr><td><img src='_layouts/images/blank.gif' ID='100' alt='Icon' border=0>&amp;nbsp;</td><td valign=top><a ID=onetleftnavbar#LABEL_ID# href='#URL#'>#LABEL#</td></tr></table></td></tr>" S-Target TAG="BODY" --></TD></TR>
           <TR><TD style="padding-left:0px;padding-right:0px"><img width=1px src='/_layouts/images/blank.gif' ID='100' alt='Icon' border=0></TD>

    Becomes this:

    <TD class="ms-navheader">&nbsp;</TD></TR>
        <TR><TD style="height: 6px">&nbsp;</TD></TR>
        <TR><TD class="ms-navheader">&nbsp;</TD></TR>
        <TR><TD style="height: 6px">&nbsp;</TD></TR>
        <TR><TD class="ms-navheader">&nbsp;</TD></TR>
        <TR><TD style="height: 6px">&nbsp;</TD></TR>
        <TR><TD class="ms-navheader">&nbsp;</TD></TR>
        <TR><TD style="height: 6px">&nbsp;</TD></TR>
        <TR><TD class="ms-navheader">&nbsp;</TD></TR>
        <TR><TD style="height: 6px">&nbsp;</TD>

    Optionally you can delete all the rows (the <TR> tags) and just have one row. Now place your mouse cursor where the empty table is and select Data | Insert Web Part Zone from the FrontPage menu. This creates a new zone where the menu was:

    <WebPartPages:WebPartZone id="{8D0A3551-0BFE-4AEA-B16E-C70539440704}" runat="server" title="Zone 1">
    </WebPartPages:WebPartZone>

    Double click on the zone in design view and change the name to something meaningful (like "Menu"). Save the page and you're good to go. Now your web designers don't have to fire up FrontPage to change your system and you can drop any web part into that area.

    Additional things you can do when you're in FrontPage:

    • Set the style of the <TD> tags to ms-bodyareaframe so any web parts you drop in here look like the rest of the page
    • Remove the "Quick Launch" image
    • Change the style of the surrounding table from ms-navframe to ms-bodyareaframe (or remove the style completely) so it doesn't stand out from the rest of the page.

    Now what can you put in this new zone? Plenty.

    You could create a custom list to hold menu links, adding columns to the list for visibility (like a checkbox called Published or Visible) then create a view that filters on that. Anytime you want to add a new menu item it's as easy as adding it a new item to the list (or changing a property of a previous one to make it appear in the view).

    There are also some great treeview web parts out there (CorasWorks has one that gives you a heirachial tree view of the entire site and there are other freebies that show you an explorer like view of your document libraries). Look around and you'll find some great stuff.

    You can also save this site as a template to recreate it easily or even replace the default.aspx page on the server so any new team sites are created with this capability. Lots of possiblities here so use your imagination.

    Additional links:

    Ian Morrish has a great article on creating a dynamic menu using Web Part Pages that exist in a document library.
    Jim Duncan has a blog on how to use a XSLT Data View and grouping to create a custom expand/collapse behavior with lists. Combine this with Ian's menu and you'll have a slick UI that's all data driven from your site.

    Have fun!

  • Access denied to your own ASP.NET application

    Every have a bad day with your ASP.NET app? Ever get the yellow screen of death with this on it:

    Access to the path "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\myapp\5607edd7\fc4d1071\hash.web" is denied.

    If you go googling for the problem, you'll find a few suggestions, solutions, ideas, and rants. We had the same problem happen at our shop a few times in the same week. In fact, it got to the point where we (the users in the local Administrator group) couldn't even access the folders themselves.

    After putting our proverbial minds to work, we did something fairly simple. We reclaimed ownership of the folders. You can do this in the security tab of the ASP.NET Temporary files directory.

    1. Right click and select "Properties"
    2. Select the "Security" tab
    3. Click on the "Advanced" button
    4. Select the "Owner" tab
    5. Select the owner (MACHINENAME\Administrators), check the "Replace owner on subcontainers and objects" and click OK

    Voila. Problem gone. App working again. Everyone is happy.