Been a pretty busy week and here in Canada we have a long weekend (still can't remember what we get the day off for but hey, who's to argue). I picked up a Compaq Presario R4000 yesterday in light of needed something to take with me to PDC and the MVP Summit coming up in September. I was originally going to get a different model but this one just looked that much better. The Athlon 64 processor and an ATI Radeon XPRESS 200M graphics card just blows away the lightweight Centrinos IMHO. It's a great machine for development as well as presentations so I'll be blogging like a madman with it down at PDC (and getting my kicks with a few rounds of Unreal Tournament 2005). Anyways, back to the grind...
Oh the horror of it all. You would think that XML is XML is XML. For whatever reason unknown to mankind, the order of CAML (and what combinations go with what) just don't add up. Some things make sense (like allowing multiple values for text fields doesn't make sense) but the order? I still have to wonder if Microsoft is using ordinal values to extract attributes from the schema as all I've done is moved an attribute to the front of the CAML statement instead of the end and BOOM! I've given up on any kind of validation tool for CAML right now because the permutations of what works and (more importantly) what doesn't is way too consuming. I am however putting together a spreadsheet with all the <Field> attributes with a cross reference against types. It goes something like this:
Attribute Attachments Boolean Choice Computed Counter etc. Aggregation No No No Yes Yes etc. AllowHyperlink No Yes Yes No No etc.
You get the idea. A matrix of what attributes are valid with what types you can define for a <Field> tag in CAML. This was put together out of frustration with what attributes I should/could use for any given type. I'll publish this for anyone who's been scratching their heads on these properties as a cheat sheet of sorts when I get it completed, hopefully by the end of the week (barring any more distractions).
Sorry, been reading the Da Vinci code too much lately (don't ask me how anyone could make a movie out of this, maybe with Dan Brown sitting in a chair counting his money for 2 hours?).
Anyways, as a follow-up to my AddFieldAsXml post there's a problem with this silly method that has provoked me to build a tool. On top of the issue with the whole Name vs. DisplayName thing, the Field CAML you pass it has to be in a certain order. Do not pass Go. Do not Collect $200. The kicker is that certain combinations of CAML make it throw a lovely exception that says (drumroll kids...) "An Error has occurred." Yup. No message (that is the message). No inner exception. A cryptic error number that couldn't possibly be a lookup into anything (especially since it's a negative number). No recovery. No hope.
What a PITA. So it prompted me to build a mini-SCHEMA.XML parser and validator. I'm just going through the matrix of combinations of attributes you can and can't use and what order they can (or cannot) be in to work. So the tool is just a silly desktop thingy. Paste in the <Field> CAML and it'll tell you if it's valid based on the rules I'm coming up with now. Like I said, there seem to be a never ending myriad of combinations that work but just as many that don't. It's very very odd, as if Microsquishy is looking for certain attributes based on ordinal position or something. So a few more hours of screwing around, digging through Reflector as far as I can go into the SharePoint libs and I'll have a tool for you to use. I'll leave it to someone to blow it out to a full blown SCHEMA.XML validator as I don't have the patience after todays SharePoint Episode from Hell. Back later with screenshots and source code.
And of course now I can't get this freakin' image out of my head. It's going to be playing all day long on my desktop.
All fields in SharePoint lists (and doclibs which are specialized lists) have two names. An Internal Name that's used by SharePoint and the Object Model (among other things) and an Display Name which is what you see in your Browser. There are four ways you can create a new field on a list in SharePoint.
- Simply use the Web Interface and add a new column. When you add the column, the name you give it at creation time is set as both the Internal Name and the Display Name. Anytime after that when you change the name you're only changing the Display Name.
- Create a custom site definition with SCHEMA.XML. Here you can set both the Internal Name and Display Name but the user would be able (with the right privledges) to change the Display Name.
- Create a field using the AddField method of the SPFieldCollection class. Here you can only set the Display Name. The Internal Name will get autogenerated by SharePoint so you have no control over it. There are rules around what that Internal Name will be and you could write your own routine to figure that out, but that's beyond the scope of this posting.
- Create a field using the AddFieldAsXml method of the SPFieldCollection class. Here it's the same thing as the previous method but you specify the CAML for the field (same CAML as you would specify in a SCHEMA.XML file). This has the most flexiblity but also has a bug which is the point of this post.
So you decide you're going to dynamically update a list using a snippet of CAML and make a call to the AddFieldAsXml method. Let's say your CAML looks something like this:
stringnewField = "<Field Type=\"Text\" "DisplayName=\"NewFieldDisplayName\" "Name=\"NewFieldInternalName\"/>";
So you expect to create a field with a Display Name of "NewFieldDisplayName" and an internal name of "NewFieldInternalName" right? Wrong. After the method call you take a look at the field. Lo and behold, SharePoint has basically ignored your request to make the internal name "NewFieldInternalName" and instead set it to "NewFieldDisplayName". Blech! That's NOT what I asked for.
The fix is a little two-step that you have to do with SharePoint to get the desired result when using the AddFieldAsXml method:
- Define your CAML so that the Internal Name you want to use is actually set as the Display Name
- Create the field with the call to AddFieldAsXml
- After the field is created, retrieve it using the internal name and set the Title property to the real Display Name you wanted it to be in the first place
So a simple little snippet to do this would be (this assumes you have some CAML and a SPFieldCollection first):
/// Adds a field as XML to a SharePoint field collection. This fixes the AddFieldAsXml bug SharePoint has.
/// <param name="fields">Field collection to add the new field to.</param>
private void AddFieldAsXml(SPFieldCollection fields)
// Declare our intent for our names here
string internalName = "NewFieldInternalName";
string displayName = "NewFieldDisplayName";
// Our definition for the CAML. Note that DisplayName is really our internal name here
string newField = "<Field Type=\"Text\" DisplayName=\"NewFieldInternalName\" Name=\"NewFieldInternalName\"/>";
// Call the SharePoint method to create the field.
// Retrieve the newly created field using the internal name
SPField field = fields[internalName];
// Reset the title to the name we want it to be (after AddFieldAsXml the display name will be the internal name)
field.Title = displayName;
// Finally commit the updates to the field
Feel free to use this and update it (maybe passing in the field names or even put it into a class). Hope that helps. Many thanks to Brian on our team for coming up with a solution.
I'm all for blogging about blogs that blog about blogs just so I can get in a blog post. Got that? So via Roy Osherove and his blog about ReSharper, the public beta is out for you to try it with Visual Studio 2005. Roy's blog came via a post by Peter Provost. Anyways, go get the new version here. ReSharper Rocks!
Update: According to Steve Eichert he uninstalled it until a more stable version comes along. YMMV.
When you click on a file in a SharePoint document library, it launches the file. Most often you'll be prompted as to what you want to do with the file (Open, Save, etc.). In some cases (like Office documents) it will open the file but the program that is doing the client side work on it, renders it in the browser. How many times have you clicked on a Word document and have it launch in the browser so you're looking at IE with an embedded Word control rendering your document. Half the time the user doesn't know what happened and when they close the browser the site is gone when really they wanted to hit the Back button to get back to their doclib. How frustrating.
Unfortunately the answer isn't an easy one, at least if you have a large deployment of users you need this to happen with. It involves setting up a property with the associated file. The setting is in the web browser, not SharePoint. The technique varies based on different environments (version of browser, version of OS, version of Office) so there’s no golden rule but the default is generally to browse in the same window (at least it has been for me on all the setups I've seen) so it will open up inside of the IE when you're accessing it through your browser. This has the effect of embedding the Microsoft Word control in the browser and hence the problem. Here’s the instructions for reconfiguring the file association in XP:
- Go to Explorer (not Internet Explorer) (or My Computer)
- Under the Tools menu choose Folder Options
- Click on the File Types tab
- Find the file extension you want to modify (say DOC for Microsoft Word Document)
- Click on the Advanced Button
- In the Edit File Type deselect “Browse in same window” for the Edit or Open actions (or all of them if you prefer)
Here's a screenie of what you should see:
This will force it to launch a new (Word) window no matter where the source of the document comes from (say a doclib in a browser). I'm pretty sure there’s a blog out on this that someone wrote but can’t find it so hence this posting (feel free to link to it in the comments if someone knows of one).
Note that there are some files that doesn't work (TXT and XML files for example). For those you may use something like the example that comes with SharePad, a GotDotNet Community Project, however it will take more than a second configuring a machine to get this to work. Also if you need to deploy this, I don't know if it's something you can include in a GPO or not so check with your network guys.
September is going to be a busy month. I'm all pumped up for PDC and spent an hour or so screwing around on Expedia.ca getting my flights and hotel and all that jazz setup. While I was booking PDC, the MVP Global Summit was 2 weeks after it so I figured I would snag my flights for that as well. At the end it was happy pills for Bil staring at my completed itinerary for the trips. Okay, so maybe you don't get so excited booking a trip but I've been locked up on a project for the last 7 months barely seeing the light of day so taking a week to geek out in L.A. is just plain refreshing. I'm staying at the Miyako Hotel, a cool looking Japanese hotel that offers shiatsu treatment rooms among other things (and
freecomplimentary high-speed internet which is a must so I can blog madly about the events). I also decided to hang around for the Saturday after the conference so I could soak in the L.A. gang wars and whatever else is going on so if you want to hook up let me know.
Fitz came back from the dead after being busy for a month or so and slams in with a note on Windows SharePoint Services and SQL Server 2005, Reading between the lines for the PDC Sessions, and a product called Longitude (which not only sounds cool but is great than we'll hopefully see some more documentation from the SPS Search team).
Snapped this up from one of the SharePoint mailing lists. It's a super cheap way to get a Google search on your site:
- Navigate to C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE
- Create a new folder called "external"
- Inside the folder create a single HTML page with the following contents:
<FORM method=GET action="http://www.google.com/search"
<A HREF="http://www.google.com/" target="blank">
<IMG SRC="http://www.google.com/logos/Logo40wht.gif" border="0"
<INPUT TYPE=text name=q size=30 maxlength=255 value="">
<INPUT type=submit name=btnG VALUE="Google Search" style="font-
- Save the file as "google.htm"
- Next drop a Page Viewer Web Part onto your page and point it to the page you created. The url to the page will be http://servername/layouts/external/google.htm
Thanks to Chris Dimarco for the information above.
I'm getting more and more impressed with Flickr, an online photo managment system, no only with the service itself but more so what people are doing with it. Roy Osherove pointed me to a service that a photographer named kaster created. You input a line of text and spell anything you want using Flickr images. Of course I had to do the obvious:
It does stir up some ideas in my head around enhancing the photo library templates in SharePoint to be more like a Flickr type interface. Better to use from a gallery perspective and you could be able to serve up images through web services, have Web Parts feed off images (like the example above). Lots of potential. Who says SharePoint is just for documents?
Check out the Flickr mod here and start creating your own unique banners or something with it.
SharePoint list definitions (found in SCHEMA.XML) have a nice feature in that you can mark a field as read-only. Just add ReadOnly="TRUE" to your field definition and the end-user will not be able to edit or change it. This is very much like a calculated field which is also read-only but a read-only field allows you to set it. Of course you'll need a way to set it so some custom code is needed but it's a great use of a status field or something through a little C# where you don't want the user changing it (even if they have FrontPage and are site admins).
However adding the ReadOnly attribute also has it's drawbacks. You will not be able to see this field in the UI unless you specifically add it to a view. Adding the ShowInEditForm="TRUE" attribute doesn't do what you might think it would. It's there to force the rendering of fields to the edit form. Any average person would think that once you do this, voila, the field will now show up on the form and since it's read-only you'll get a display of it that nobody can edit right? Wrong. There's no way that I can concievably find that will show a field on either the new form (when adding and item/document) or the edit form. I tried the Viewable="TRUE" attribute but that didn't work either. You can use it on views as it's available there but for forms it just doesn't show up.
Inversely if you add the attribute Hidden="TRUE" to your field definition you'll never see it. Handy for storing stuff in lists that you don't want anyone to get at, but if just remember it's there as it won't show up normally.
While looking through my referrals (yeah, I need a life) I found one from Computerworld which was odd because I had never blogged there nor did anyone that I (normally) know did that linked to my posts. It Seems Mikes article keeps making its rounds and this time ended up in a mish-mash article that lumped "Dell clueless, SharePoint annoying, and Longhorn teaseful" all together. Nice.
What's wrong with Sharepoint? Long-time Microsoft consultant Mike Drips tells us. Paul Schaeflein rebuts some points and later summarizes other posts. MS blogger Robert Scoble responds, adding his own list. IBM blogger Ed Brill finds the blog responses from the MS community "interesting." Canadian MVP Bill Simser has his own take. Ferris Research is looking for your opinions and offering a nice bribe inducement.
Now if we could just generate as much energy over helping understand and make the product better the world might be an easier place to live.
P.S. Can't anyone ever spell my first name right? I know it's odd but is too much to ask?
Registered last night for PDC (to make the early bird cutoff and save $300). You have until this Friday to cash in on the savings, otherwise you'll pay the full price of $1995USD. Hope to see various bloggers, MVPs, Micrsoquishy guys, and anyone else there. Now I need a good Wi-Fi notebook to take with me to capture notes and do some blogging during the 5 day conference. I've been looking at Motion Computings LS800 as it's smaller than a laptop but bigger than a PDA, but then Alienwares Area-51m 7700 looks too sweet to not get. Let me know what you guys think. The big thing of course is all the new SharePoint stuff as Microsoft will be letting loose and not holding anything back on the next release for SharePoint as well as Office 12 (or whatever it will be called). So get your butt to PDC and see you there!
Okay, Saturday was a bad day for me and after reading Ed Brill's blog on the whole Mike Drips article (and my response which he quoted a few times) I decided to delete the post. It's the first time I've done that and I normally wouldn't but in reality the post was my emotions getting the better of me and taking it out more against Mike than the content of his post. Daniel McPherson makes some good comments about getting to the bottom of "what's wrong" with SharePoint and ways that the team can fix it. I think we all agree there are things wrong with SharePoint but it's not a bucket of bolts that has no purpose or value. It's just articles that are primarily negative seem to cast a shadow so people new to the scene might not get both sides of the story (hence why I'm leaving my Five Things Right With SharePoint post). So back to being the kinder and more gentler SharePoint guy that I should be.
While Mr. Drips got his shots in (and I did my own share of mudslinging) I thought I would take the time to come out with my own spin on this and present the five things right with SharePoint. Feel free to agree or disagree with me, add your own, or go have a protein shake.
1. Quick and Easy Creation and Collaboration
This is probably one of SharePoints biggest features and the easiest to use. Want to get some teams that are geographically disjointed, can't rely on email for communications, and don't have time to set meetings up with everyone? A team site is just what is needed and brings everyone together in a quick and easy way. Where else can you offload site creation with a self-driven service and yet still monitor and be able to throttle users on how much storage they take up (or remind people about inactive sites for those that were just "playing").
Far too many people shun SharePoint because it doesn't do this or that out of the box and expect much more. If you take a step back and look at what you have and not what you don't, you'll find a vast set of resources that can be used for not only simple collaborative team sites but help desks, knowledge bases, employee performance tracking, wikis, blogs, and much much more. While there are physical limitations on implementations, the sky is the limit on your imagination.
2. .NET and Web Services
Let's face it, building business solutions is tough no matter what technology is out there. For the most part though, business solutions are really quite easy. Really. Their hasn't been a complex business problem that I've seen yet. Complicated perhaps. Many moving parts maybe. But actually complex, not so much. When you can start leveraging things like SSO and talking to infrastructure services that don't require complex data models to keep track of simple things, SharePoint just works. Add to that the fact that most of the major large vendors out there (Seibel, SAP, etc.) are giving away Web Parts for your sites to talk to their products.
No longer do I have to hand bomb some crazy ass service to connect to my Enterprise systems. I have extensibility and expandability. With more and more people out there writing .NET components, Web Parts are naturally springing up to solve various problems and fill some gaps people have been wanting the product to do (like RSS feeds). I can now tie my sites into Enterprise tools with minimal effort, attach to pre-built accelerators that provide a piece of functionality, and custom build systems that suite my specific business needs. All from one interface delivered, managed, and secured through the web. That's not so bad.
3. Integration with Office and other Microsoft Products
Open a Microsoft Word document from your hard drive and you'll get the usual gammet of features. Open one from a SharePoint site and you'll have a vast amount of new things that will not only help increase your productivity and put you in touch with teams but it will also give you new things like presence and status. Click on a user column and I can now access my colleagues calendars, availability, and contact information. The fact that the mere presence of a product in my environment and that it changes the behavior of other products is pretty interesting, but I can also leverage this and rather than building custom chat tools or deal with the inadequacies of web editing, just let them use Word. Complete with custom properties I can build views and groupings of documents that should drive people away from the archaic file systems folder heirarchy where I can't group things by two different values.
Throw on top of that a workflow engine out of BizTalk and sophisticated data entry via InfoPath forms (all stored in SharePoint) and I can start building things like automated recruiting systems that get me away from the crazy email and phone based solutions (or custom built systems) just to ensure a new hire has a computer. This can be looked at as an early incarnation if you will of Software Factories in action but stay tuned as it can only get better.
4. Microsoft's commitment to evolving an ongoing suite of tools
Microsoft has made it clear that SharePoint is a key player in the Office space and the tool to enable you to deliver collaborative solutions. Let's face it, Office has been pretty stagnant since it's inception. What great new features have you seen in Microsoft Word in the past 10 years? Collaboration and productivity is becoming the core of the Office Suite now as you just can't get any better with a word processor or a spreadsheet.
SharePoint 2003 was a test-bed for creating the next generation Web Sites and you see this in .NET 2.0 with the Web Part framework being expanded out and SharePoint and .NET 2.0 coming together. This isn't a half-baked idea that just evolved into something large and unruly, these are ideas and concepts that stretch back to the early days and now come full circle to provide a platform rather than a tool or technology. If you think SQL Server is just a database, you probably think SharePoint is just a web site. It's that and much more and Microsoft is behind this for the long run.
5. The SharePoint Community
While I go on and rave about how great this platform is, it does have it's shortcomings. However there are a lot of resources out there. Looking back to when we had SharePoint 2001 and the 5 of us that blogged about it, we now have over 100 dedicated people that are always writing about new things they're discovering, answering questions, and creating new tools. Go on. Go out and ask.
More often than not, the problem has already been solved and someone is more than willing to share. If not, it becomes a challenge for those of us that wish to take up the gauntlet. The SharePoint community is quite large and grows each day but it is a community and a two-way street. A street that you can either play on or help pave. I for one welcome our new portal overlords, you should too.
PDC is the bomb and I'm excited to be able to go this year. Yes, even more excited than TechEd which I didn't get to go to and whined about it for many posts. Like a good
whinewine (or woman for that part) the best part of PDC is waiting in anticipation for it. Channel 9 has their PDC contest going strong for another month so see my auto-magic post below. I think I'm doing pretty good on standings so far. Last time I checked (a couple of days ago) I was in the one of the top 3 or 4.
Not bad for the portal guy who whines
winesa lot. Of course this is just on referrals alone and we all know its also about content and not just clicks (feel free to use that sometime as it has a nice ring to it). In any case, here's another pathetic plea for you to send a geek to Los Angeles for a week of debugging and debauchery.
Hmmm, update. I just checked the PDC05 Contest Sightings page and found that Steve Hebert is WAAAAAAY out front now with 164. Also a bunch of others have crept up in the last few days leaving me back down in the dust. Guess everyone found Steve's blog and hey, why not vote for the smarter dude. Anyways, maybe the SharePoint community will take pity on me and help an old portal guy out. Here's the updated standings (counting all referrals):
Steve Hebert: 164
Roy Osherove: 92
This time I'm using Brendan Tompkins most excellent Web Service to write my entry. Brendan took it upon himself to be creative on his entry and think outside of the box. Rather than writing some funny or provocative or even useful (like Roy Osherove who posted his RegEx blog and then decided to give a fine tutorial on Regular Expressions to boot) Brendan built a Web Service that you can call to create the blog entry for you. I was one of the first ones to try it out and it's great. Brendan personally has my vote to go. Anyways, check out his service if you want your own blog entry and join the club. Simply brilliant.
Here's what you need to quickly bang something together and get the results delivered to you in a string:
private void Form1_Load(object sender, System.EventArgs e)
EntryServiceRequest request = new EntryServiceRequest();
request.BlogUrl = "http://weblogs.asp.net/bsimser";
request.FirstName = "Bil";
request.LastName = "Simser";
request.Interests = ".NET, C#, ASP.NET, SharePoint, Agile, DDD, TDD";
PDCContestEntryService service = new PDCContestEntryService();
EntryServiceResponse response = service.CreateBlogPostEntry(request);
textBox1.Text = response.PostBody;
Then just cut and paste the results (from response.PostBody) into your blog. Mine follows below. Guess I need to get a little more worldly as far as Amazon is concerned. And hey, while you're scrolling down the page feel free to click on the bloggie icon and bump up my counter. Yeah, I need to take as many cheap shots as I can as we get into the home stretch, this won't be the last grovelling from me on this.
You really don't want me whining for another week about how I couldn't go and if I do win, you'll get my lovely blow-by-blow commentary on all things SharePoint and .NET 2.0 that I stumble over and after a few drinks we'll kick up a live demonstration of Whack-A-Fitz.
I’m Blog’n my way to the PDC!
If you haven’t heard, Channel9 has started a contest where you can win a ticket to the PDC, including an airline ticket and hotel! This is one amazing contest, and all you have to do to enter is have a blog, and post why you should win the prize. So here’s my official entry:
Here's some information to help you get to know me better:
Why do I want to go to the PDC? Because I love to blog! And I'm prolific! Here's some of my more popular blog posts links according to Google :
- SharePoint Version Bug
- Fear and Loathing
- SPS Customization
- Syncronization of Office Document Properties with WSS Document ...
- Adjusting the DisplaySize of your Fields
What are my interests?
Well, here’s a list of books that I'll probably be reading on the plane to LAX :I'm not very interesting according to Amazon.
Did I type up all this ugly HTML for this Blog post myself?
Heck no! I’m lazy! But that’s exactly why I need to go to PDC! The PDC is all about the future, and in the future, we’ll all be using cool technology to do things like typing tedious, boring contest entries. I’m getting a head start on the salad days, so I figured out how to use ASMX web service that Brendan wrote! To prove it, you can see that I'm on this list of other, lazy coders who would rather sit back and use a distributed Web Service to do their work!
Hope everyone had a good holiday. I know the Americans did the big fireworks display for the 4th and as usual, in Canada, we had two guys in a fishing boat with a flare gun.
I've been looking at reporting solutions in SharePoint, specifically building reporting around data kept in SharePoint itself and not necessarily reporting on SharePoint but more business-specific reporting. On the SharePoint reporting side, there are a lot of great options like the recently released SQL Server Report Pack. That's great if you're looking at reporting on how SharePoint itself is doing, the site collections, how many documents are in each site, etc. but what if you want to know how well sales are doing when you store the sales figures in a SharePoint list?
If you build a business application using SharePoint and store the business information in SharePoint lists then getting the information out is like pulling teeth. All reporting tools (Crystal, BusinessObjects, SQL, etc.) need a datasource for the information. None of them can use SharePoint lists as a datasource. The closest you can get is using the SharePoint List Web Service to get the information out, but even then it's not very good either. So far the solution I'm going down is using a .NET managed reporting tool (ActiveReports for .NET from Data Dynamics) and just creating an XML datasource that represents my business objects (mostly through serialization in my business layer which isn't the best). Just wondering if anyone has any other solutions for this type of problem?
This week has been pretty busy so I haven't even got to my blog backlog as well it was a bit of a living hell for me as we were experiencing various problems with a few common components that provide mail which in turn required us to do a quick "comment out" code release to demo a product. Anyways, now that that's over and it's July 1st (Canada Day, much like Independance Day that Americans will celebrate on the 4th but without the aliens).
I was on one of my more favorite geek sites, The Code Project, and found an interesting article that resonated with the SharePoint side of my brain. The author wasn't too happy with the lack of design support for building ASP.NET server controls (as are all of us that write Web Parts) and came up with an interesting solution to the problem. He uses an approach similar to string.Format to inject controls into a composite control layout string. After a couple of iterations he then took the HTML page for his composite control and made it an embedded resource in his server control and this became the layout string to inject the controls into.
The same principle can be easily applied to Web Parts. Just create a new embedded resource which is your HTML layout then in your CreateChildControls call, create the controls and inject them using the layout file. It still has it's drawbacks so something like SmartPart and User Controls give you the design-time capabilities that this doesn't offer, but it's a good alternative if you're struggling writing out gobs of HTML in your codebase and doesn't require deployment of .ascx pages or anything. Check out the Code Project article here.