Fear and Loathing
Gonzo blogging from the Annie Leibovitz of the software development world.
-
NOT going to TechEd and tracking down a SharePoint bug
Unfortunately due to project commitments I'm stuck here in Cowtown for the week instead of basking in Florida at TechEd 2005. So expect a week of bitching and griping with at least a blog a day where I mention how craptastic it is as I read my fellow bloggers entries about how fab it is down there (and if you're blogging from down there, raise a glass to the poor schmuck here in rainy Calgary).
I'm also tracking down a potential bug with SharePoint document libraries and single quote characters. Thanks to the resources of my team (way to go guys) we may have uncovered something that needs a hotfix (at least it's critical enough for us to have one). I still need to confirm it as I can't seem to find anything in any MSKB I've looked through (both public and private) so stay tuned.
-
Copy and Paste in Explorer View
I've ranted before about Explorer view and how it basically screws with your version history. This is basically why I delete it on most document libraries I roll out. So if you copy and paste a document (or a series of documents) from one Explorer View to another here's what you get:
- The document is copied across from source to destination
- An entry in the version history is created in the destination library for each entry in the source document library
- All versions point to the unique copies of the document in the destination library but the document itself is the latest version from the source document library
- Comments for each version are not brought across
YMMV. At least this is what I experience whenever I do it. Might be my infrastructure that is causing this but I've tried it with various browsers, end user operating systems, and service packs and get the same results. Try it out with your own setup and let me know if you get the same results.
Update Note: Got an email from my fellow Canuck on the other side of our country Amanda Murphy about their product called Trace. Looks pretty nice and adds a cut/copy command to the menu and the ability to resolve conflicts (like mapping columns) when you paste a document into a new doclib. So check it out here. If you buy it remember to mention my name so I can get my $1 commission (kidding about that Amanda).
-
Whack-A-Fitz
Fitz has been pretty quiet lately but he always resurfaces and pops up like those damned Whack-A-Mole games from time to time. I wonder what they have him doing as he's been quiet for a few weeks now (and I prodded him a couple of times in email with no response, which basically means nothing but thought I would throw that in). Anyways, he's got a nice short post on this year's Professional Developers Conference and to keep an eye on the Office/SharePoint Development Track. He dropped a hint of this awhile ago but now it looks more solid. While I hate the fact that I can't attend Tech-Ed this year and drink heavily and hang out in the SharePoint Cabana, not even a free X-Box 360 will prevent me from getting my butt down to PDC. Looks like SharePoint is going to kick into overdrive and re-enforce the message big Bill gave about SharePoint being one of the key collaboration technologies in the Office Space and Microsoft will be letting us peek at what we can expect next year.
-
Any ill effects if the crawler is removed?
Yup, asking today instead of sharing. Ever have your SharePoint domain crawler account show up in every @$%!%!&*!@ list where there's a user lookup. I seem to have them in any of the sites we have spun up around here. A freaky looking account name that nobody seems to know who it is (ours is called spsSpider).
So the question is, are there any ill effects removing the name from the profiles? I mean, the account is setup in the Central Admin and part of the admin group so it should have access. I guess when it "visits" the site to crawl it, it leaves its name droppings there just like any user but is there any problem removing the accounts profile from the SharePoint Profile Database. Does it come back when the next crawl happens? Is there any way to get rid of it so your users don't see it or maybe I should rename the account to Alan Smithee (heavy thud as nobody gets that joke)?
-
FabriKam on MSDN
A few weeks ago I order the FabriKam DVD. It never arrived so I guess my order was never processed or delivered. However you can get the FabriKam DVD off of MSDN downloads now. It's under Tools, SDKs, and DDKs | Application Tools, SDKs, DDKs | FabriKam 3.1 and just under 2GB to download. Once downloaded you need to unzip the VPC image which will create your .vmc and .vhd files for running under VirtualPC or Virtual Server 2005.
I spent most of yesterday going through the VM and it looks pretty good. Lots of great source code, tons of documentation and a fully installed and working system out of the box to play with. Includes SQL Server, SharePoint, and BizTalk along with the solution files, source code, etc. Very slick. I did find some of the Web Parts were listed as being unsafe so I had to do a re-registration of them for some of the solutions to work but that could have been me (I was running as Administrator rather than one of the FabriKam users).
If you're looking for business solutions and ideas that use SharePoint, InfoPath, and BizTalk it's a great learning tool to start with.
EDIT: Some people have mentioned they can't find the file. I only have a Universal MSDN account I'm not sure if they've made it available to professional and other MSDN subscriptions but you do need an MSDN subscription to get it. The path is listed above starting under the Tools, SDKs, and DDKs menu in the MSDN downloads. You can try the path here but not sure if it will work for everyone (you will need to sign in via Passport).
-
Adjusting the DisplaySize of your Fields
Yesterday I mentioned I would post an entry on YAUSF (Yet-Another-Undocumented-SharePoint-Feature) however I think this one will be around to stay.
When you create a list you can specify the maximum length on Text fields. This is great and will provide a warning message to the user if they enter text that exceeds this. However it doesn't (always) adjust the length displayed on the screen so most SharePoint lists look like this:
Of course with a simple tweak in SCHEMA.XML you can have your SharePoint lists looking like this:
The list for the first image is your typical field definition for the columns. Here's the snippet from SCHEMA.XML:
<Fields>
<Field Name="Title" ReadOnly="TRUE" Required="FALSE" Hidden="TRUE"/>
<Field Name="Name" DisplayName="Name" Type="Text" />
<Field Name="Address" DisplayName="Address" Type="Text" />
<Field Name="City" DisplayName="City" Type="Text" />
<Field Name="Country" DisplayName="Country" Type="Text" />
</Fields>In SharePoint fields, there's a property called DisplaySize. Yeah, looking through the SDK won't find it in the Field element in SCHEMA.XML. In fact, you don't find it in any SCHEMA.XML file anywhere (which might be why it's not in the SDK, unsupported perhaps?). You will find it however as a Property on the SPField class. This might lead you to think that you have to write a custom program to adjust the display length of all your fields if you want to give your users something more. Not so.
While I was digging around in FLDTYPES.XML yesterday and screwing around with the RenderPattern there was another thing that stood out. DisplaySize was a property being checked and if it was there, it was used in the creation of the HTML tags outputting in the browser. So with a little tweak to SCHEMA.XML I added DisplaySize to a few fields like so:
<Fields>
<Field Name="Title" ReadOnly="TRUE" Required="FALSE" Hidden="TRUE"/>
<Field Name="Name" DisplayName="Name" Type="Text" DisplaySize="30" />
<Field Name="Address" DisplayName="Address" Type="Text" />
<Field Name="City" DisplayName="City" Type="Text" DisplaySize="20" />
<Field Name="Country" DisplayName="Country" Type="Text" DisplaySize="15" />
</Fields>Now you get the much improved version of your list for your users to add and edit items to. This made sense as the property would alter the length of the field in the UI when it gets built in OWS.JS. Through the regular SharePoint interface you can specify the length of your fields. This will prevent the user from entering more than the number of characters here in the field but does it adjust the UI? It depends.
If you create the fields as show in the second image with the field lengths indicated, you'll get the display you see on the screen above. All done through the UI. If you don't specify a length or you change a field so it is longer than 31 characters, it will stretch the UI display out to 50 characters wide (like the Address field above). 50 characters seems to be the max width and while you can create fields that are 255 long, they'll only ever display 50 characters wide. Through the UI. If however you edit your SCHEMA.XML for the list like above and set the DisplaySize tag to whatever you want, it will appear correctly not matter what the value is.
So if you've been paying attention:
- Creating columns through the UI only respect the length if it is less than 32 characters
- Columns longer than 31 characters through the UI will always fill out to 50 characters wide in the Browser, no matter what the length
- Specifying DisplaySize in SCHEMA.XML for a field will display correctly in the Browser for any length
Anyways, mildly bizzare and slightly odd. Differences between what you can do in site definition files vs. what (normally) your users can do isn't always the same.
-
Unlocking the elusive TelephonePattern... almost
I spent a few hours this morning chasing down a new SharePoint unicorn. Unfortunately I haven't found the solution but it's close. Real close. My rule is that if I can't crack the secret in a few hours I'll post or email someone and see if someone can complete the work. 10,000 monkeys must be smarter than 1.
Have you ever built a custom list and had a telephone field that looked like this:
That's the normal way you have to define a telephone field. With a plain ordinary text field (or you could use a number field if you want). But there's no way to format this stuff for end users. Wouldn't it be great if you could have THIS!
Well, you can. Or at least Microsoft was *thinking* about letting you have it. The above image isn't a custom web part. It's just a regular list but with a *secret* option. I just haven't figured out how to get it to completely work.
Deep in the heart of a file called FLDTYPES.XML (one of those dont-touch-this-or-you-will-be-unsupported files) lies the heart of something just waiting to get out. FLDTYPES.XML defines all of those columns you can add to a list (Text, DateTime, Number, Calculated, Lookup, etc.) and it also determines the way the fields are rendered for the various forms (New, Edit, Display, etc.) through something called RenderPattern. If you dissect the Text field's RenderPattern you'll find a switch on a property called Format. The default value is to just write out some JavaScript to create a new TextField:
<Default>
<HTML><![CDATA[<SCRIPT>fld = new TextField(frm,]]></HTML>
<ScriptQuote>
<Property Select="Name"/>
</ScriptQuote>
<HTML>,</HTML>
<ScriptQuote>
<Property Select="DisplayName"/>
</ScriptQuote>
</Default>This will result in writing out the following JavaScript fld = new TextField(frm, "Name", "DisplayName"); into the browser and through a method in OWS.JS it will create a text field like in Image 1 above. However if a property called Format is set to Telephone you get this instead:
<Case Value="Telephone">
<HTML><![CDATA[<SCRIPT>fld = new TelephonePattern(frm,]]></HTML>
<ScriptQuote>
<Property Select="Name"/>
</ScriptQuote>
<HTML>,</HTML>
<ScriptQuote>
<Property Select="DisplayName"/>
</ScriptQuote>
</Case>This will result in writing out the following JavasScript fld = new TelephonePattern(frm, "Name", "DisplayName"); to the browser which will create the 2nd image above. Cool. However it doesn't work. So first we create our Text field in a custom list using the SCHEMA.XML and add our Format="Telephone" value:
<Fields>
<Field Name="Title" DisplayName="Title" Required="TRUE"/>
<Field Name="ContactTelephone" Type="Text" DisplayName="Telephone" Format="Telephone" />
</Fields>This gets us our form and the data entry looks good. There's even separate validators created for each part of the field so if you make the ContactTelephone field required, it will require the area code and phone number (doesn't need a country code). Saving the item will result in a nasty message from SharePoint:
Error
No such field name
No field was found with that name. Check the name, and try again.
So now what? If you take a look at OWS.JS you'll see that when it actually makes the call to create the TelephonePattern, it actually creates a bunch of TextFields. One for each part of the phone number (country code, area code, number). So I figured if SharePoint couldn't save it, it was because there were these new fields that didn't know how to map to the record in the list (after all I only had one field, ContactTelephone). The code in OWS.JS seems to create new fields and gives them the naming pattern of "TelephonePattern#countryCode:" + the internal name of the field for the phone. So I modified my list definition to create some hidden fields to hold those values like so:
<Fields>
<Field Name="Title" DisplayName="Title" Required="TRUE"/>
<Field Name="ContactTelephone" Type="Text" DisplayName="Telephone" Format="Telephone" />
<Field Name="TelephonePattern#countryCode:ContactTelephone" Type="Text" DisplayName="Telephone" Hidden="TRUE" />
<Field Name="TelephonePattern#nationalCode:ContactTelephone" Type="Text" DisplayName="Telephone" Hidden="TRUE" />
<Field Name="TelephonePattern#number:ContactTelephone" Type="Text" DisplayName="Telephone" Hidden="TRUE" />
</Fields>Here I thought we're all set. I deployed the list and entered a new item. Field displayed correctly, validation happened and it saved! Nice. However when you look at the list (through something like SharePoint Explorer) you'll see the fields but they're all set to null.
So that leaves us puzzled and moving onto other things. You can get the Telephone to display correctly and save correctly with those fields in there. Just no values. As the Telephone format is not documented in SDK, it's one of those things that is left up to the reader. If I use it will it be supported? It's there in FLDTYPES.XML which is a core file of SharePoint however since it's not documented, you might think it will be removed in a future release.
Tommorow I'll blog about another undocumented property which does work and I *think* should be there in fhe future. If anyone completes this investigation and gets the Telephone format working please drop me a note through the comments of this entry!
-
CAML and Date Formats
Patrick beat me to the punch and posted about date formatting with CAML (it was sitting in my blog TODO pile, I *knew* I should have blogged last night). The date format works alone and will return values. I just wanted to add to his post that you can add a time to the date as well if you want to a query for a particular time. For dates with time the format of the query has to be:
<Query>
<Where>
<Leq>
<FieldRef Name="EventDate" />
<Value Type="DateTime">2005-05-27T16:00:00Z</Value>
</Leq>
</Where>
</Query>
So this would return all items in a list that has a field called EventDate with a value before 4:00PM on Friday, May 27, 2005.
-
Don't Modify your Output Path. Really.
Todays read is an excercise in balance. The balance is between what Microsoft says and what Microsoft says about development, specifically creating Web Parts. Buried deep in the best practices around the build process is a quote. "Don't Alter the Build Output Path". The section that's relevant goes on to say:
You might be tempted to alter the output paths of your projects in order to build to a single folder and then establish file references to that folder. Do not do this for the following reasons:
- It causes the build process to fail with file lock errors when a referenced assembly exceeds 64 KB in size. This problem is likely to be fixed in a future version of Visual Studio .NET.
- You can encounter another problem when you reference an assembly from a folder that is designated as your project's output folder. In this event, Visual Studio .NET cannot take a local copy of the assembly because the source and destination folders for the copy operation are the same. If you subsequently remove the reference from your project, Visual Studio .NET deletes the "local" working copy. Because the local folder is the same as the assembly's original folder, the original assembly is deleted.
Any developer worth his salt and building Web Parts probably knows that buried deep in the SPS/WSS SDK is this little tidbit:
Specify the build output path
This task assumes that you are running Visual Studio .NET on a server running Windows SharePoint Services or SharePoint Portal Server. Setting the build output path to the C:\inetpub\wwwroot\bin folder will build your Web Part's assembly in the same location from which it will run on your server. If you are not running Visual Studio .NET on your computer, you can copy your Web Part's assembly to the folder C:\inetpub\wwwroot\bin folder on your server after building it.So on one hand we have Microsoft telling us to not change the Output path, and another we have them telling us to do it. Now for most of you, changing it has never been a problem. You set it to c:\inetpub\wwwroot\bin and all is well. Your Web Part compiles and runs and you can do all kinds of things like debugging and good stuff like that. On a larger project this isn't true so heads up to those about to approch the platform. Once airborne, it's an ugly trip back.
On larger projects there can be lots of Web Parts. Our current project (a Contract Management System) has about 40 of them but even that might be considered small. However all the Web Parts are reletively thin (as they should be) and just simply make calls to a Service Layer to retrieve Domain Objects and update the views. Nothing fancy and nothing complicated. All 40+ Web Parts compile to less than 64k. We have a single assembly that represents the Business and Data Access Layer. They're combined just because everything is sitting on the SharePoint server anyways and the DAL is just a wrapper around accessing lists using the SharePoint Object Model so again it has to be local.
It hasn't been a problem so far and we, as documented in the SDK, changed our output path to c:\inetpub\wwwroot\bin for development. Debugging and all that goodness abounds. The problem was this morning when I added a new assembly to handle communications with a third party system (SAP). SAP (via the .NET connector) creates proxy classes for you and these can change frequently and have to be regenerated so the assembly will change often. I didn't want to keep changing our Core assembly whenever SAP changed (because every Web Part referenced it) so it was split out. Herein lies the problem that surfaced. Now the system was referencing an assembly larger than 64k and, due to circular references in the assemblies, I couldn't avoid this. There were a few other things I tried with separating and combining classes but it's just not going to happen.
So now it's back to resetting all 40+ projects to compile to bin\Debug again and creating an extra NAnt task to do an xcopy deployment to the c:\inetpub\wwwroot\bin directory for debugging. A bit of a PITA but has to be done and it fixes the issue. As Microosft says "this will be fixed in a future version of Visual Studio .NET". I checked and compiled with Beta 2 and it seems to be fixed but then I can't fully check it because I can't run Beta 2 against SharePoint just yet.
Bottom line, follow the first rule and don't modify your Output path and use a build script to copy the files after a successful build. Even if your project is small today, someday it might grow. So do you want the pain now or later?
-
ListFormWebPart and Tzuanmi SharePoint Designer
Last Friday I posed the question of being able to create "more than SharePoint but less than InfoPath" input forms without having to resort to writing an entire facade on top of a SharePoint List. Didn't get any response to things but I did some digging into the WebPartPages namespace. Microsoft creates a raft of WebParts that are used to create the SharePoint UI itself. The ListFormWebPart and ListViewWebPart are particularly interesting as you just point them at a list and they're supposed to handle all the heavy lifting of generating forms and views. And they do. All of the .aspx pages for lists use them so that's how all the extra columns you add to lists and document libraries appear when you add/edit an item or document. The ListFormWebPart just automagically creates the form on the fly by interrogating the list, getting the fields and their datatypes, and creating the various controls (TextBox, CheckBox, Dropdown, Calendar, etc.) for you.
Anyways, I thought I would be clever (I always think I'm clever when I do these things) to create one of these things (they're sealed so you can't inherit your own Web Part from them) and render it in my own Web Part. Before the render (in the pre-render event) I could just grab the contents of the Web Part and make some "on-the-fly" modifications (like joining up dropdowns, etc.). That idea is a bust because as hard as I try, I can't do anything with the ListFormWebPart once it's been created. I can create it fine, set the list name and all that jazz but it always seems to render an empty Web Part. Poking around inside Reflector didn't show me much either (is SharePoint really that proprietary that Microsoft has to obfuscate the code?) so I'm at a loss how to tap these classes. Even though they're sealed, I don't recall anywhere Microsoft saying you can't use them (some classes are marked for internal use only, but not these ones). Just use them for good, not evil. Anyways, the quest goes on and I'll continue to post my findings here as I try to discover a value for them outside of what SharePoint does with them.
Tzunami SharePoint Designer. I spent most of my Memorial/Victoria day looking at this new tool. Tzunami used to be the old K-Wise guys (there were some tools for SharePoint 2001 from them like K-Doc if I recall). The Designer is meant to be a tool that you can bascially build up your entire portal structure offline, saving it in various iterations to a local file (after sucking down the initial site from a SharePoint server), then committing those changes back to SharePoint to create everything. The tool is just coming out and has some growing to do but the initial reaction is pretty good. There are a couple of things that I noticed with this version:
- There's a Disconnect option but it seems to clear the project's contents. So you're really always connected to the server but it's not like being in the web interface where everything you do is committed immediately. With Designer you must invoke the commit through a menu which then hooks up and creates/updates all your lists and whatnot. Personally I think the model isn't quite right. I would rather be able to work completely offline and then sync up (say when I got back to the office after spending 300 hours on a plane ride designing my portal). Maybe that's a feature to come. It seems like it could support it.
- There are a bunch of features that are grayed out in this version like copy and move but I'm told they're coming.
- There are some elements of editing things like document libraries (like say exposing it on the Quick Launch) that are not present in the interface. Again, I'm told these are coming.
The biggest thing that is mulling in my noodle is the fact that you can alter creation and modification dates on things like lists and list items. I need to do some digging to see how they're doing this because the properties through the Object Model are read-only so methinks they're doing something down at the database layer because I can't see how else they accomplish this. That bothers me for two reasons. First, never ever ever ever ever (did I say ever) touch the database directly. Period. Do not pass Go. Do not collect your versioned documents. There's just so much going on behind the scenes with transactions and logging and synchronization and other SQL stuff oh my. Even if you go through the documented stored procs Microsoft just won't support you and there are so many things that can go very, very bad doing this.
Second, while there are a lot of people that jump up and scream when they try to migrate their data into SharePoint and generally rant about how it can't retain the original dates and such, I personally believe there's good reason why those things are read-only for developers in the Object Model. Basically it's a CYA thing. Yes, your developers do need access to be able to make changes to a site but do you really want them with the ability to alter that information once it's set? With all the SOX stuff going on, it's a good thing that when you write an item to a list you'll always know who created it and when it was last modified. Hold on, now with a single tool I can alter history! I can say "No, you didn't create that document on Monday May 13, 2001. Bob created it on Friday June 3, 2002." No, that's not a feature I want to enable. As well, there's a question of data integrity. SharePoint doesn't have a lot of it. I can delete a lookup value in a list or a user from Active Directory and depending on the phase of the moon, the information may or may not be there later. However I can always be rest assured that something silly will never happen like a modification date being set earlier than a documents creation date. Well, that's out the window now with this tool and if I did have any reports I created on aging those are probably going to take some explaining now.
Anyways, if you into cutting edge tools and don't want to wait you can contact them to get a trial version. Like I said, there are some features missing and some features you might not want to have. The support guys are excellent and responsive so if you do have any questions they'll be happy to answer. The trial runs for something like 7 days and has a limited number of commits you can make to the server.