Thursday, 28 October 2010

Free Antivirus for Windows Server 2008

I've been a long time home user of Avast! antivirus. It's a great product that doesn't bog down my machine. Unfortunately the free home edition won't install on Windows Server 2008 R2 and I run a single-boot W2k8 environment because of my Hyper-V love affair.

Don't get me wrong, I normally despise AV and security in any form… the guys I work with are probably fed up with me always shouting "security != productivity" when the bloody proxy policy has once again broken something or prevented me doing my job. But, every now and then, I feel incline to download evil things and God forbid those things include a virus of some kind—a quick scan would then come in handy…

ClamWin to the rescue! Don't know about the name but it doesn't include a real-time scanner which meets my requirements. So far so good… evil things downloaded and appear to be virus free!

Wednesday, 27 October 2010

Empty ImageUrl results in empty src and duplicate request

Not exactly a new issue but an empty ASP.NET ImageUrl tripped us up today. In this case there were no visible symptoms but two requests were coming through when Fiddlering the page view: the first initiated by the user and the second initiated by the page itself towards the end of the trace. In development with a debugger attached, this was manifest with Page_Load, CreateChildControls, etc being called twice for no obvious reason.

Because I initially thought I introduced the problem with the control I was working on, I first attempted to convince ASP.NET CreateChildControls was complete; I did so by clearing the Controls collection before unleashing my own code and setting the ChildControlsCreated property true once done. Neither of these tricks had any affect and the Fiddler trace had me convinced something beyond the ASP.NET pipeline and IIS had to be at fault.

That turned out to be the case but ASP.NET was still to blame ;-)

Specifically, we were adding a server-side ASP.NET image control but not initialising its ImageUrl property; the image src was later being set by jQuery at runtime on the client side. As mentioned, there were no visible symptoms of the double request: the image src was set as expected by jQuery and everything appeared okay on the surface. The IE dev toolbar also showed image src as being correctly set and there were no 404s in the mix.

It wasn't until we looked at the raw HTML that our ever-faithful admin extraordinaire noticed the empty src="" attribute. Removing the attribute removed the problem so I can only conclude IE is helpful enough to attempt to interpret a request for an empty image as a request for the parent directory of the current page while parsing the HTML before any Javascript runs. Thanks again, IE!

Notably this problem wasn't reproducible in Firefox or Chrome.

To fix the problem, we first set a default value for the ImageUrl property but that left me feeling dirty since it was still resulting in an unnecessary request. When I realised the server-side Image tag wasn't actually being used for anything server-side anyway, I replaced it with a boring old HTML img tag with no src. Microsoft has other, equally lame workarounds for this if you're interested; note they also don't plan to fix this bug.

If you found this post helpful, please support my advertisers.

Friday, 15 October 2010

Must-know SharePoint debugging tips

This post is a follow-on to my Must-Know Visual Studio debugging tips article; I'm separating out my SharePoint debugging tips focused on list, feature, and solution deployment that don't relate to Visual Studio.

Here you go:

  • Try activating your feature without the –force attribute; you'll likely need to deactivate the feature first
  • Try uninstalling and reinstalling the feature
  • If something stuck and rebooting seems to clear some kind of cache deep inside SharePoint, stop IIS and restart the various SharePoint Windows services

@echo off
@echo Stopping services...
iisreset /stop /noforce
net stop "Windows SharePoint Services Timer"
net stop "Windows SharePoint Services Administration"
net stop "Office SharePoint Server Search"
net stop "Windows SharePoint Services Search"
net stop "Windows SharePoint Services Tracing"
@echo Starting services...
net start "Windows SharePoint Services Tracing"
net start "Windows SharePoint Services Search"
net start "Office SharePoint Server Search"
net start "Windows SharePoint Services Administration"
net start "Windows SharePoint Services Timer"
iisreset /start
@pause

  • Create a new list from your list definition (or at least, a new list item)
  • Rebuild your solution and redeploy
If you found this post helpful, please support my advertisers.

Thursday, 14 October 2010

The Mysterious SourceID Attribute

I see a lot field definitions around that unnecessarily include a SourceID attribute:

<Field
SourceID="http://schemas.microsoft.com/sharepoint/v3"

More often than not, the value of this attribute is set as above. Microsoft's own documentation samples tend to include this attribute.

So what does it do? Not a lot as far as I can tell; I don't include it with my own field definitions because inspecting the field after deployment with SharePoint Manager proves SharePoint sets it automatically with the GUID of the list that created the field. The Field Element documentation also indicates it is optional.

If you're intent on using it, the documentation describes this attribute as "containing the namespace that defines the field, such as http://schemas.microsoft.com/sharepoint/v3" so rather than use the default namespace it may be advisable to use your own (I haven't tried this myself).

If you found this post helpful, please support my advertisers.

Wednesday, 13 October 2010

SharePoint and Chrome - Better Together

I've been using Google's Chrome browser since its first release in 2008; I've loved nearly every second of the experience. Who would've thought there was room left to innovate in the browser space? Chrome's omnibar and rapid-fire JavaScript rendering, among other tweaks, are simply light years ahead of the competition.

While I normally rely on IE for my MOSS/SharePoint editing interactions, as of late I'm making the switch to Chrome in that space as well. What I've found to date has blown my mind.

Yes the MOSS 2007 UI degrades somewhat but it's still very useable. More importantly, Chrome drastically reduces the time it takes to accomplish basic tasks like modifying page content or viewing list data. I'm not saying these are normally slow in SharePoint but they can be in the www.westernaustralia.com environment (it's an ageing site with a lot of content and a lot of customisations); some pages in particular nearly grind to a halt in IE8 with the corresponding process consuming upwards of 1GB of memory the more I interact with the page.

Chrome "fixes" many of these slowdowns I'd previously attributed to the SharePoint environment and gives me all the Chrome goodness I've come to love over the last two years. It almost makes the SharePoint editing experience pleasurable!

If you found this post helpful, please support my advertisers.

Monday, 13 September 2010

How to pass JSON arrays and other data types to an ASMX web service

Ah interoperability… great fun, great fun.

So jQuery is your new best friend and, along with JSON, there's nuthin' you can't do. The server side stuff is still there in the background and you've got some old school ASP.NET (.asmx) web services hanging around but DOM elements are otherwise flying all over the place, postbacks are just so passé, and even the marketing girls are mildly impressed at your skillz. You're branching out, shifting code and complexity from the server to the browser, and it's time to do some heavier data shunting. Here a few things to know about passing JSON data to an ASMX web service that may help you on your way…

JSON.stringify

Know it, use it, love it. It's part of the JSON2 library and you need it if you don't have it already. Use it to prepare (aka properly encode) your JSON data before sending it off to the big mean ol' web server:

data: {"days": JSON.stringify(["Mon", "Tues"])}

That will encode as &days=["Monday","Tuesday"]

Yeah, I know, it's another file to download but the guy who wrote JSON also wrote this and it can be merged and minified. I've tried writing my own mini-version as a function and while this works for simple strings, save yourself some time when it comes to arrays and the like and just use this sucker.

Arrays

Arrays seem trickier than they should… maybe I'm just a dumb guy—probably. Anyway, you can pass a JSON array to an .asmx web service without much work at all.

The client-side call listed above is everything you need to do from that end. On the server side, create yourself a new web service method with a List<string> parameter:

[WebMethod]
[ScriptMethod (UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string ConsumeArray (List<string> days)
{…}

That's all there is to it. If you're not passing in strings, declare the List<> parameter with a type of object or something else. You can use .NET arrays in the web method signature as well if you really want (need) to.

Integers

When in doubt, stringify:

data: { "i": JSON.stringify(2) }

An int parameter on the web service end will handle this graciously.

Booleans

The good ol' boolean—a simple concept computer science has managed to bastardise like no other…

When in doubt, stringify:

data: { "b": jsonpEncode("true") }

Like the int parameter, a bool in your web method signature will take care of this.

A brief note: JSON, or rather jQuery's parseJSON function, is a particular beast and doesn't seem to know about anything other than the lower case true and false strings. If, for any reason, you ToString a bool in your .NET web service and try to pass it back, parseJSON will fail. If you forget to brush your teeth in the morning, parseJSON will fail.

Dates

Sorry, on my todo list ;-)

Tools

When working through this stuff, it pays to have Fiddler open to inspect the requests you're sending through and any error messages you're getting back. I find Fiddler sometimes breaks this stuff so try turning off the capture if you're getting weird errors; optionally, revert to Firebug (Firefox only, of course).

Fully decoding the data you sniff from a JSONP request passed along in the query string will require some additional tooling; in short, you'll want to decode the value using a free online tool like Opinionated Geek's URL decoder.

If you found this post helpful, please support my advertisers.

Wednesday, 8 September 2010

Exposing the Global Assembly Cache

If you're familiar with the Global Assembly Cache (GAC) you're probably aware there's a special file system viewer thingy (technical term) sitting over top of the GAC contents at c:\windows\assembly; this is a nice convenience when it comes to registering assemblies in the GAC—simply drag and drop, avoiding a trip to the command line and gacutil –i

More often than not, this is all good. When you need to dive into the real GAC, to extract an assembly, drop in debugging symbols, or whatever, you'll quickly realise the viewer is somewhat limiting.

To get past the GAC's outer facade, you've got a few options:

  • From a command line, browse to c:\windows\assembly\gac_msil
  • Map a network drive to \\machine-name\c$\windows\assembly\gac_msil
  • Create a virtual drive: subst z: c:\windows\assembly\gac_msil where 'z:' is any unmapped drive letter
  • Start –> Run c:\windows\assembly\gac_msil
  • Turn off the viewer altogether to browse the GAC directory structure normally within Windows Explorer: create a new DWORD named DisableCacheViewer with a value of 1 below the HKLM\Software\Microsoft\Fusion key

Five ways to do the same thing? Well this is Windows after all—and there are probably more!!! ;)

If you drop the gac_msil bit you'll find there are other directories that make up the GAC proper to explorer but most of what you'll be after resides below gac_msil. Each assembly is represented in by name as a folder with different versions represented as sub folders named as the version number with a GUID appended; the assembly proper will live in one of these folders.

If you found this post helpful, please support my advertisers.

Changing a VS2010 SharePoint package name

The SharePoint development tooling built into Visual Studio 2010 does a pretty good job at hiding some of the ugly bits involved in creating a SharePoint solution file. No longer must we deal with ddf files (hooray!) but we also lose some control (or, at the very least, have to dig a bit further to change some things that were previously "easy" in the broader context of "really painful").

One of those things that we previously had full control over was the name of the solution file (.wsp) that results from our ddf file and the mighty makecab.exe. While the file name is now set from within Visual Studio, you have to open the package designer before being presented with the package properties:

Rename-solution-file-vs2010
Simply clicking on the Package.package file will present you with the file properties which is not what you want—you have to double-click/open the package designer.

The one thing I used to do with the ol' ddf file was specify the extension as .cab instead of .wsp. This was a convenience thing—SharePoint doesn't care about the extension (or at least doesn't object to .cab files)—but a .cab file will open in Windows Explorer on machines where you don't have a better archive tool installed like my favourite, 7zip. Essentially, it just saved me having to rename the file by hand.

Unfortunately I have yet to find a way to do this with VS2010; the package name is only that—Visual Studio appends ".wsp" to the end of whatever name you supply and I can't find a way to override that behaviour. In truth I'll probably just start using .wsp like everyone else but it may be possible to tweak the file name in one of the pre/post events.

If you found this post helpful, please support my advertisers.

Monday, 6 September 2010

.NET 4.0 application compatibility

Looks like those of us running SharePoint may be stuck on .NET 3.5 SP1 for a while longer but that's no excuse not to have .NET 4.0 installed side-by-side for use by other apps. One of the guys on the team, for instance, recently updated the custom crawler we run and needed pull in some of the Entity Framework features only made available in the 4.0 release; of course Microsoft will tell you the various .NET runtimes can be installed to run side-by-side and we managed to get away with a lot during the whole 2.0/3.0/3.5 onion thing.

Of course this all gets interesting very quickly when you've got a console application built against 4.0 that references assemblies (i.e. the SharePoint assemblies) built against version 2.0. Naturally everything worked fine in dev but as soon as we hit UAT, this exception cropped up:

An error has occured: Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information. [sic]

To address this, a simple .config element was added:

<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>

Notably, the useLegacyV2RuntimeActivationPolicy="true" attribute was required and we found this out the hard way by not having in place initially (dodgy internet code most likely!).

If you found this post helpful, please support my advertisers.

Friday, 3 September 2010

Detection of product '{90140000-104C-0000-1000-0000000FF1CE}', feature 'PeopleILM', component '{1C12B6E6-898C-4D58-9774-AAAFBDFE273C}' failed

After sorting out a problem with the FIM Service not starting automatically after a reboot and several resultant application event log errors, there was one more thing to clean up: running a user profile sync would spit a couple of MsiInstaller warnings about product detection failing (see below).

Various users in the forums suggested granting the Network Service account read access to the C:\Program Files\Microsoft Office Servers\14.0\Service directory and/or the C:\Program Files\Microsoft Office Servers\14.0\Sql directory; I initially found only the latter was required (this directory currently has Read & execute, List folder contents, and Read) but on reboot, the same warnings were logged again. Granting the same access to \Services had the same result and I've found starting a crawl produces these warnings but they go away with subsequent crawls. Reboot and they're back :-(

This change relates to the following warnings logged as a crawl is initialised:

Log Name:      Application
Source:        MsiInstaller
Date:          2/09/2010 3:40:24 PM
Event ID:      1004
Task Category: None
Level:         Warning
Keywords:      Classic
User:          NETWORK SERVICE
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
Detection of product '{90140000-104C-0000-1000-0000000FF1CE}', feature 'PeopleILM', component '{1C12B6E6-898C-4D58-9774-AAAFBDFE273C}' failed.  The resource 'C:\Program Files\Microsoft Office Servers\14.0\Service\Microsoft.ResourceManagement.Service.exe' does not exist.

Log Name:      Application
Source:        MsiInstaller
Date:          2/09/2010 3:40:24 PM
Event ID:      1001
Task Category: None
Level:         Warning
Keywords:      Classic
User:          NETWORK SERVICE
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
Detection of product '{90140000-104C-0000-1000-0000000FF1CE}', feature 'PeopleILM' failed during request for component '{9AE4D8E0-D3F6-47A8-8FAE-38496FE32FF5}'

Log Name:      Application
Source:        MsiInstaller
Date:          2/09/2010 3:40:24 PM
Event ID:      1015
Task Category: None
Level:         Warning
Keywords:      Classic
User:          NETWORK SERVICE
Computer:      dev-sps2010-01.dev.mediawhole.com
Description:
Failed to connect to server. Error: 0x80070005

If you found this post helpful, please support my advertisers.