Thursday, November 29, 2007

Note To Self: SharePoint Queries

I've just spent the last, uh, 6 hours trying to figure out why a query I've been writing in SharePoint would not filter the returned data properly. It would always return more data than I was anticipating. Consider the following snippet:

sopv = "{" + soplib.Views["WS_Browse"].ID.ToString().ToUpper() + "}";
sopq = new CamlQuery(CAML.Where(yaddi yaddi yadda)).CreateQuery();
sopmtch = soplib.GetItems(sopq, sopv);

In the first line I'm fetching a friendly handle to the name of a view I've built in a document library. I had constructed the view inside SharePoint and specified the columns I wanted returned as well as including a filter so it would weed some of the gunk out before my own filter ran over it in the query.


In the second line I'm using John Holliday's CAML.net to build the query xml, and in the last line I'm running the query, specifying the query object and the view name in the method call.


For the life of me I couldn't figure out why in the Sam Hill it was returning more items than I was expecting. It wasn't returning everything, but just one or two more than I was expecting. And the one or two extra were definitely outside the range I was yaddi yaddi yadda'ing about.


So my next step was to crack open U2U's CAML Query Builder application and reconstruct the query in what I knew was a working a environment. Voila, the query worked perfectly. And theeeeeen, I outputted the actual query xml from my SPQuery object (sopq) and compared it to the query xml generated by U2U's tool. Identical!


At this point I was really getting creeped out, thinking that there was some bug in using the SharePoint object model to run queries vs. using the SharePoint web services (which is what I was doing with the U2U tool). As a last ditch effort I removed the view specification from the GetItems method. BINGO.


So, you know what? I learned something today! If you specify a view to use in your query the SharePoint query processor happily ignores the CAML you've whipped up. Not very nice considering the effort it takes to to put one together that doesn't get stuck in SharePoint's throat.


And while I have your attention, I'd like to make the following public service announcements:



  1. John Holliday's CAML.Net is a great shortcut for creating CAML, although even a somewhat simple query can lose you if you put it all on one line. I'll have to check out his Visual Studio plugin.

  2. The U2U CAML Query Builder rocks. I would actually use it more often and just store the raw, generated queries in text files, but I wanted the flexibility of making queries up on the fly. At the very least it's a good debugging tool.

  3. The existence of CAML is hella-silly. I mean, it's just dreadful. XML and SQL, two not-so-great tastes that taste like [ expletive deleted ] together.

  4. Programming data operations in SharePoint, in general, is an abomination. In fact, at the end of a day of programming data operations in SharePoint, I can't wait to stop and ram shards of glass in my eyes. For you DBA types, just consider writing queries as I have described in the previous point. Now consider doing that plus doing data joins manually. Hallelujah... where's the Tylenol!

Wednesday, November 28, 2007

This Is A Test of the Emergency Broadcast System

I've just downloaded Windows Live Writer and hooked it up to this blog. Just testing to see how well it works with Blogger.

So far it looks like it takes a copy of your template from Blogger and uses the CSS when you are writing, so you have an idea of what the final output is going to look like. Sweet. The functionality is also offline, so I don't have to be on Blogger's site when writing/saving/editing posts/drafts.

One thing that it does seem to be lacking is the ability to use Blogger's label function. Maybe it's time to use the labeling/tagging function of a third party site.

Update: Duh. It's a nomenclature issue, not to mention a near-sightedness issue. There is a categories field below the posting window (they are called "labels" in Blogger), along with a field for force-setting the publishing date. NICE. What's not so nice is the interface for selecting/entering the category.

Update II: You can add plugins, of which there are a bevy. For instance, there is one for Picasa and for Flickr, which I often use for hosting images for this blog. SCHWEET.

Monday, November 19, 2007

Crisped

I followed with great interest the 2007 San Diego fires. The San Diego fires of 2004 narrowly missed the home in Ramona I lived in when I graduated from high school. In fact, it burned the house down across the street. The fire this year, although larger, did not seem to get very close to any of the places I've lived, worked, or schooled at.

It did burn down a place I'm familiar with though. Noting that the fire started between Ramona and Julian and burned due eastward I wondered if it took down the trailer park where my ex-wife's grandparents used to live (I say "used to" because her grandmother died a while back and I'm pretty sure her grandfather would not be alive today... and the street burned down anyway). My father and I went out to survey the damage this past Saturday and we went by the old trailer park. Needless to say, tornadoes aren't the only thing which easily prey on trailer parks. The homes surrounding the park stood up, as well as the community center in the middle of the park which is a regular building.

This photo is what I believe to be the remains of trailer, although I don't remember which one it was exactly. If you follow this link you'll get a panorama of the street my ex's grandparents lived on. You can also follow the map information in the lower right with which you can bring up a satellite view of the area, which (currently) shows the area as it was before being burned down.

Coming: Text Displays On Shopping Carts

Text displays on shopping carts, which seems like the first step of an idea I barfed up a couple years ago.



Via: Ubergizmo

Thursday, November 15, 2007

Righteous

For those of you who use remote desktop to get to your servers or other computers often, give Terminals a try. It stacks up all your remote connections into a single, tabbed window which unclutters your taskbar.


Via: Mike and Duncan (no, I was not doing a Paris Hilton search)

Wednesday, November 14, 2007

Drive eRazer

Behold, the "Drive eRazer." Plug it into your IDE drive and it provides an unattended wipe-out session. There appears to be a regular version that does a one-pass job and a "pro" version which does multi-pass in the event that you are extremely paranoid.

Nifty. I may have to pick one of these up.


Via: Boing Boing

Friday, November 09, 2007

Separated At Birth



Dave Mustaine, grand poo bah of Megadeth and Faramir (aka David Wenham) from Lord of the Rings.

Global Warming Resource

ICECAP.

Well, it won't be your resource if you think we're burning our planet away, but it works for you fairly well if you want a reasoned, unhysterical look at global climate change.

Thursday, November 08, 2007

Web Service: GetGuid

OK, this is the first method I've put in this set of free web services. Why GetGuid?

I had a need to grab a GUID in javascript from time-to-time but had my doubts that it could be done in earnest in javascript. There are a few implements hanging around where random base16 characters are strung together in a GUID-like format, but this algorithm doesn't fall under the "official" designation of GUID and I guess allows for a greater chance of generating a duplicate GUID (although I think those chances are infinitesimal).

So, this web service exists as it calls upon the GUID-creating ability of Microsoft SQL Server. I chose this route rather than the GUID methods in the .Net framework because I've been working on getting my database chops back up to snuff and this seemed like a pretty low-stress way of starting that. In any event, it should be a true GUID and technically the numbers should never duplicate.



Method: GetGuid
JSON Parameters:
  1. op -- set to "GetGuid".
  2. cb -- set to the name of your javascript function you want called back.
Returns:
GUID in string format.

Free Web Services

So, every once in a while I'll run into a programming conundrum in something I'm working on and either wish there was something I could download and implement fairly quickly or that there was a web service hanging "out there" that I could hook in to.

Well, I guess I'm going to start my own set of web services and leave them hanging "out there" for me to use, and anyone else who is brave enough to use something they are not hosting themselves. I'll be hosting it on my forthcoming company website at the following urls:

http://lpsol.com/ws/soap.asmx
http://lpsol.com/ws/json.ashx

Yes, I'll be providing both soap and json interfaces. The soap interface is generally useful in standard web services calls, although to implement into your own AJAX-based website or webapp you'll have to write a proxy running on your site which will then access this web service.

Not so with the json interface, though. All you'll need to do is include the json url in your web page using a script tag and the proper querystrings to call the function you want, and the service will call back the function of your choice (specified in the querystring) and pass in the requested data as a parameter.

While the jsoninterface doesn't include it's own description page, if you click the soap url above you'll find information on how to call each method using soap. When consuming a web service in the .Net environment you generally get a nice class and set of methods to call from the web service -- the Intellisense kicks in and shows you the parameters you need to pass in a what-not. Not sure how it works in other environments.

For the json calls you'll have to specify the "op" and "cb" querystrings manually for each method you call. The "op" is short for operation and is the name of the method. "cb" is short for "callback" and is the name of the function you want the server to call back when it's done. For instance, when calling the "GetGuid" method (details on this method forthcoming) you will set "op" to "GetGuid", and if you want the server to call back your javascript method called "procGuid" after it's generated, you would set "cb" to "procGuid". Therefore, the whole tag would look like this:
<script type="text/javascript" src="http://lpsol.com/ws/json.ashx?op=GetGuid&cb=procGuid"></script>
If either of those parameters are omitted then an error is thrown by using an alert. Other parameters may be required on a per method basis.

The data returned from both interfaces will formatted in a similar fashion. The packet will be in two pieces, an "error package" and a "data package" encapsulated inside a "return package." You can actually see this arrangement if you run the GetGuid method through the soap url or pasting the value of the src parameter from the above script tag in your browser address bar.

The error package will always contain the following pieces of information:
  1. Flag. This will either be True or False, indicating if an error occurred.
  2. Message. The error message.
  3. StackTrace. The stack of methods called leading up to the error. Probably not very useful to you, but useful to me in figuring out the problem.
  4. AdditionalInfo. This may contain any other useful tidbits I stuffed in there before pushing everything back to the browser.
The contents of the data package will vary. I'll try to include detailed information for each method. I have a few more idea for new methods that I'll work on at some point, and requests for new methods are also welcome.

Lastly, in the event that these services gather any traction, I'll try to keep all related posts tagged with the "lpsws" label.

Enjoy.

Thursday, November 01, 2007

God Hates Fred Phelps

The man for whom the term "jackass" was invented and his church have been ordered to pay almost 11 large to the family of Matthew Snyder, the Lance Corporal who was killed in Iraq and rewarded for it by having his funeral picketed by Phelps and his mentally ill acolytes.

There is also a response by Phelps in a CNN intereview here. My vote is that Phelps is senile.