How I passed 70-417

Hot on the heels of writing about How I passed 70-480 I decided to start studying for the exam 70-417 – Upgrading Your Skills to MCSA Windows Server 2012. This was probably the most difficult exam i’ve approached for quite some time having historically been a SharePoint developer first, a SharePoint administrator second and a Windows administrator a very distant third. So maybe it’s just me, but this exam was hard. It doesn’t help that if you fail any one of the 3 sub-sections to the exam, you’ll fail the lot. I was lucky to scrape by with one of my scores barely making the cut, even if the other 2 scores were much better.

But before I get into the details of how I passed 70-417, I want to comment a little about my overall thoughts of the exam, or more particularly the suitability for it to exist as part of the SharePoint 2013 administration certification stream. Feel free to skip this rant and find the ‘Resources I used for 70-417’ heading to cut to the chase.

My thoughts about 70-417 for a SharePoint certification

So I could only make wild presumptions in regards to why we now have to complete these pre-requisites to gain the overall certification. The cynic in me would suggest its a convenient way to increase the amount of course and exam fees they’ll rake in from this decision. The realist in me would appreciate that for anyone to be certified in SharePoint (and for that certification to mean something) they probably need a broader skillset than the specifics required for the 2007-2010 certification streams. Having pre-requisites are a reasonable way to demonstrate that.

The problem I have though is with the MCITP: SharePoint Administrator 2010 certification being a valid pre-requisite for 70-417 and then that being the basis for showing the required level of knowledge for a SharePoint Administrator qualification.

Point 1: I wasn’t upgrading my knowledge at all. I was learning the majority of this from scratch. Now I would NOT have been happy if I had to essentially become a certified Windows administrator as a pre-requisite to becoming a certified SharePoint administrator (that is, completing all 3 individual exams which make up 70-417 – costing over $600 just to sit them in the process) but i’m not sure this was the right compromise.

Point 2: I’ve now essentially demonstrated that I know a bit about the new features of Server 2012 and how this has changed from previous Server versions. While this knowledge was interesting, it was not all particularly relevant to being the best SharePoint administrator I could be.

Point 3: I still feel like I have a lot to learn. I feel my study could have been far more productive if it was more specifically focussed on content which was more relevant.

What would I have liked to have seen? I think rather than taking the easy (lazy) option of having us do 70-417, they should have created a SharePoint-specific exam which could truely prove the candidate had the required Windows administrator skillset most relevant to being a SharePoint administrator. This would not necessarily have been upgraded skills, because i’d suggest a number of people would have been in my boat – had the SharePoint knowledge and perhaps experience without ever really having to dive into the Windows administrator world (most teams I’ve been involved in have already had these specific team members).

Anyway that’s probably enough of that, on to the good stuff!

Resources I used for 70-417

It seems every exam I do these days I take a different study path. For this one, because I wasn’t at all confident with the material, I invested a fair amount of time (easily over 40 hours). I watched some study videos again after having some success with that method when I passed 70-668 (although I now have learnt the time-saving capabilities of playing videos at 1.8x speed in VLC player!). The video resources i’m aware of include Pluralsight’s Windows Server category (which includes videos for the individual exams 410, 411 & 412), CBT Nugget’s more targeted 70-417 Upgrading Skills to Server 2012 and Channel 9’s Exam Prep’s for 70-410/70-417, 70-411/70-417 and 70-412/70-417. There are also Jump Start videos at Windows Server 2012 Upgrade Jump Start.

I also for the first time read one of Microsoft Publishing’s exam references Exam Ref 70-417: Upgrading Your Skills to MCSA Windows Server 2012. To be perfectly honest, if I hadn’t had read this book, I probably would have failed. I would perhaps only read them in these circumstances in the future where I wasn’t at all comfortable with the content, but it has definitely opened my eyes to the option.

I also read a tonne of TechNet and other articles relating to topics I still wasn’t particularly comfortable with, however I didn’t do this in my usual structured way – more so via search engines. But that’s not particularly helpful to you, so I’d suggest checking out Enduria’s Preparation resources for the exam 70-417 for individually linked TechNet articles.

The final resources I believe are worth referencing are Vlad Catrinescu’s I passed 70-417, MCSA Windows Server 2012! and Free Windows Server 2012 Learning Material & Resources! Part 1 and Keith Mayer’s “Early Experts” Challenge – Apprentice Quest. All 3 posts are worth reading through and link to some decent resources for this exam.

To wrap things up i’d have to say my overall feeling is one of relief – relief that I passed and can finally put this lot behind me and get back into learning about SharePoint more specifically. My experience wasn’t as negative as Patrick Kremer’s MCSA 2012 upgrade exam experience – MS 70-417 but I can see where he’s come from and to an extent I agree about the value of this certification, if perhaps for different reasons. I wouldn’t say don’t bother though – chances are you want that MSCE SharePoint Certification and this one is a means to an end. It did have some value, but there’s room for improvement. I believe Microsoft have the right idea including a wider range of topics for an overall SharePoint certification, but I hope they change the way they go about certifying it.

Good luck!

Advertisements

How I passed 70-668

This post sees the end of my series on working through passing the SharePoint 2010 certification exams. It may be a little delayed, however it hasn’t been too long since I gained the MCITP: SharePoint Administrator 2010 certification by passing 70-668. It’s a great feeling to have all 4 certifications under my belt now and opens up the door to a range of new challenges to work towards – none more so than exploring everything SharePoint 2013 has to offer (including the certification paths in the future I’m sure!).

But first things first – how I passed 70-668. The title to this post may even be a bit misleading, because I’m going to discuss a number of avenues I could have taken to pass the exam. In reality I felt that I had a pretty good understanding of the theory behind a lot of the skills measured and ended up relying on the reading I had already done for 70-667 along with a few study videos to get through. It was interesting to compare the different paths I took for each exam both in terms of knowledge gained and the exam results which followed.

So firstly the path I did take – there are a few study videos available to learn SharePoint 2010 administration and I was keen to try them out, not having done so in the past (not counting the Ignite series). A few examples include LearnSmart’s SharePoint 2010 Administration Video Training, CBT Nuggets’ Microsoft SharePoint 2010 Admin 70-668 and PluralSight’s SharePoint 2010 Administrator Ramp-Up.

Overall I’m undecided on the video route – in terms of targeted knowledge I believe it is the best way to go. In terms of having the information sink in and motivating myself to study, I’d rate them fairly highly. In terms of getting the overall breadth of coverage you get from trawling through copious amounts of TechNet and MSDN study material it wouldn’t quite be up there (not to mention sometimes the answers to questions come directly from that content!). The time you dedicate to it depends on how fast you can read – whereas the videos take a set amount of time, reading articles or a book allow you to skim through sections without fear of missing something important. I’d suggest I would be prepared to go down this route again both to specifically target an exam and get a decent amount of knowledge up front, however I’d prefer not to do it at the expense of reading a book or Microsoft’s documentation in the long run.

So what other options were available? Surprisingly, a great deal. In fact I seemed to find more quality resources for 70-668 than I did for 70-667. First up, Microsoft can always be relied on to provide some decent ‘amalgamation’ pages, especially for the newer versions of the platform. Their SharePoint Server 2010 for IT pros page is a good place to start your deep dive into the content. There’s also the videos and virtual environments they provide which I have previously listed in How I passed 70-667. This was the first time however I’ve stumbled across actual usable learning plans – my memory of these were always a link to a course or paid online training, but it seems like they’ve got some decent content attached these days – something I definitely want to check out in the future.

On top of what Microsoft provide there was also a number of quality blog posts all in different styles which would certainly help preparing for the exam. There is Joel Jeffery’s generic SharePoint Exam Tips and Barry’s SharePoint 2010 70-668 Study Guide links. Scott Jamison wrote a great piece on Preparing for 70-668: PRO: Microsoft SharePoint 2010, Administrator and Alex Dean wrote some handy tips on How to Pass 70-668.

Finally, much like for 70-667, Accelerated Ideas has provided some practice exam questions which will help you get a feel for the type of information you’ll need to know to pass the exam.

Overall my 70-668 experience was very good – somewhat surprisingly I actually scored my highest mark in this one out of the lot – it may have had something to do with the fact it was the last one I took and a lot of the information you study for overall is transferable. The one thing to look out for with this exam is the different style of questions you’ll be faced with – it’s no longer simply a matter of taking a 25% stab in the dark for a lot of questions – there are case studies, ‘mega’ multi-choice with 15+ options and perhaps the most difficult style, ordering various steps to achieve a particular task (while ignoring the steps that shouldn’t be there!). If you’ve read up on the links presented on this site however, or perhaps watched some of the videos available, you should be ready for success. Good luck!

How I passed 70-667

Part three of my ‘Certification Series’ delves in to how I recently passed 70-667 – TS: Microsoft SharePoint 2010, Configuring. It was always going to be a bit of a challenge stepping back up to the administrator certification plate (I had achieved administrator certification in the 2007 stream) after having a heavy focus both in development and also predominantly on the 2007 platform for the past year and a half, however I’m happy to say with the preparation I followed I managed to pass reasonably comfortably.

I took somewhat of a different approach to studying this exam in that, for the first time heading into an exam, I decided to base a large proportion of my preparation time reading a book. Without turning this article into a book review or commentary on what the best book out there for studying for this exam would be, I can say that the book I read, Professional SharePoint 2010 Administration, was a really good read in terms of learning a few things that I previously had not known. Whether it helped achieve the certification in the end i’m not sure (there ended up being a few months difference between finishing the book and sitting the exam) but regardless it was a good read and one I would definitely recommend.

Closer to the examination date I chose to go back to my tried-and-true method of finding a blog post which highlighted all the relevant Technet and MSDN articles on the skills measured for the exam. Not surprisingly, as I did for 70-573, I found that Becky Bertram’s post Exam 70-667 Study Guide covered everything I would need to read for each point and is the site I chose to go through.

I would however suggest that there is an even better resource when it comes to studying for the 667 exam and that is Benjamin Athawes series How I passed SharePoint 2010 exam 70-667 (part 1, 2, 3 and 4). The reason I didn’t use his articles as a guide for my study was simply due to time – I thought I had enough experience and knowledge already to get by without that level of study – however as a starting point for someone without the experience it would definitely be my number 1 suggestion on where to start.

Unfortunately, unlike the Cram Session videos I used for the developer exams which were extremely helpful, I couldn’t find anything similar for the administration stream. What I did find (some of which I had viewed previously) were some decent video content on Technet including Getting started with SharePoint Server 2010 for IT pros and SharePoint 2010 advanced IT pro training.

In the interest of completeness, like I did in my 70-576 post, I thought it would also be useful to highlight some of the training and labs available to help pass this exam, even though I didn’t use it in my own personal study plan. The labs available on TechNet Virtual Labs: SharePoint Products and Technologies are definitely worth exploring for those without enough hands on administrative experience.

Finally there was one pretty cool resource that I stumbled upon and perused briefly, Accelerated Idea’s Free Practice Exam – MCTS: SharePoint 2010, Configuration. It’s a neat little tool to help get you used to the multiple choice format of the Prometric exams and give you a little bit of confidence going into the administration certification (assuming you do well – I wouldn’t be overly concerned if you didn’t, the questions in this practice test are fairly broad and not necessarily indicative of what you’ll face in 70-667).

So that covers it. In the end I actually found the exam a little harder than I expected. I thought I’d blitz it but I’m glad I put the effort in to learn all the content being tested, not only as I picked up a few things I didn’t know but it definitely helped me pass in the end. The final piece to the puzzle will be 70-668 which I hope to attempt some time soon, but until then, all the best achieving 70-667!

Harnessing SignalR in SharePoint

Note: For those interested in the implementation of SignalR in SharePoint 2013, view the latest post Harnessing SignalR in SharePoint 2013 (Office 365)

On the 1st of April Bil Simser wrote an article Introducing SharePointR. I happened to read it on the 3rd and as such it wasn’t until I got to the ‘quote’ by David Fowler that I tweaked to what was going on. It was a clever April Fools post and likely got a lot of people excited. For me, it piqued my interest. I’d heard of SignalR in passing but had yet to delve into it. Once I had, I have to say I got pretty excited myself. It’s super cool. I, along with one of my extremely talented colleagues Elliot Wood, went about getting SignalR up and running in a SharePoint environment.

SignalR is relatively new and as such the information available isn’t extensive, but what is out there is pretty good. There are a few examples you should check out right off the bat: Scott Hanselman’s Asynchronous scalable web applications with real-time persistent long-running connections with SignalR and Justin Schwartzenberger’s Learn how to use SignalR and Knockout in an ASP.NET MVC 3 web application to handle real-time UX updates were the two I found to start with. Both link off to a number of other valuable examples.

So what is SignalR? Essentially, it’s real-time client-server communication on the web. Without having to constantly poll or perform any refreshes, data on the page will ‘magically’ update in front of your eyes. The library is maintained on Github which gives you access to the latest code, issues and documentation at a central source. I’m not going to go too far into what it is, because with the excitement that’s being generated around this, plenty of other people are doing a far better job of it than what I could. I’ll skip straight to the fun stuff.

So if the examples are already out there, why can’t we just plug this straight into SharePoint?

The majority of examples which currently exist tend to host the hub and the client in the same project, and hence are hosted on the same domain. This works great, you can spin up your .NET 4.0 web application and everything will work smoothly. Only problem being SharePoint runs on the .NET 2.0 framework – you won’t be able to add the SignalR DLLs to your SharePoint project.

This however is not a deal-breaker. As long as your hub is hosted on a .NET 4.0 web application you can leverage SignalR in a simple HTML file with JavaScript, so surely that would be easy enough to plug into a SharePoint web part?

Firstly; it’s not exactly simple. It requires something called Cross-Domain Calling which I’ve since found out is a bit of a pain to get working across different browsers. This is where the information fell down a little, or at least was scattered around. I’ve read more StackExchange and Github Issues than I care to dig back up and link to for this article so excuse my lack of referencing here. One page I did come across which got me most of the way there was Thomas Krause’s Making Cross-Domain Calls in SignalR which summed it up pretty nicely, but still didn’t work in all browsers for me. But more on this later.

Secondly; even with all those issues resolved we still want a way to trigger SignalR to broadcast an update from SharePoint, and unless you’re doing that purely with client interaction in the UI, chances are that’s going to mean handling create, update and delete events via event receivers. Which brings us back to our first issue – these will be on the .NET 2.0 framework and won’t be able to reference the SignalR DLLs. So how do we get around this?

Essentially what is required is a bridge between SharePoint’s .NET 2.0 environment and a .NET 4.0 one. I liked the way Elliot termed this better: breaking the .NET barrier. My initial thoughts were hosting a WCF service and passing the information from the event receiver to that service to be broadcast by SignalR, and I still think that would be the ideal solution. Elliot however beat me to the implementation by making the leap via HTTP and posting to a handler sending the information via Query String, and for the purposes of the proof of concept (minimal data being transfered) this did the trick nicely.

With all the pieces of the puzzle in place, it’s time to implement our SignalR in SharePoint proof of concept. The idea is pretty simple – consider it a mini task-tracking system. Tasks will get added to the pile and others will be completed. The service quality manager will have a dashboard on their monitor open all day receiving live information on whether performance targets are being hit on a day-to-day basis. Let this be a glimpse into the power of what SignalR can achieve and let your imagination run wild on possible real-world implementations.

Step 1: Create the Hub

The Hub needs to be a .NET 4.0 web application. The majority of examples on the net state the first step of implementing any SignalR application is to use nuget to retrieve the SignalR DLLs and scripts. This is fine in theory, but while we were investigating our cross-browser issues (non-performance in Firefox and Chrome) Elliot noticed that the nuget version of SignalR is not the latest, therefore downloading the latest ZIP and re-referencing the DLLs is the way to go. In fact the ‘latest’ version from Github at the time of writing included another required DLL that the nuget version didn’t bring across – SignalR.Hosting.Common.dll. Others that you’ll want the updated version for (or at least the ones we used) include SignalR.dll, SignalR.Hosting.AspNet.dll and Newtonsoft.Json.dll.

The next step is to add an entry into the web.config file to allow the cross-domain calls. This requires adding the following snippet to the system.webServer node

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
  </customHeaders>
</httpProtocol>

The final step is to add a class to your project to house the Hub

using SignalR.Hubs;

namespace SignalRHub
{
  public class SharePointHub : Hub
  {
    public void Send(string message)
    {
      // Call the addMessage method on all clients
      Clients.addMessage(message);
    }
  }
}

At this point all the extraneous components of the project can be removed so you’re left with the class, the web.config and packages.config. Just a note – the Send implementation is somewhat redundant as we’ll be calling the client script from the handler below rather than the hub itself – but it’s useful for testing.

Step 2: Create the HTTP Handler

The handler can exist in the same project created above and will essentially be the tool to receive the Query String data from SharePoint and broadcast it via SignalR to the clients. All credit here goes to Elliot for the concept, I’ve adapted it to match my SignalR implementation (I used a Hub, he used a Persistent Connection).

One major thing to point out is that the documentation currently offers this as the method of broadcasting over a Hub from outside of a Hub

using SignalR.Infrastructure;

IConnectionManager connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
dynamic clients = connectionManager.GetClients<MyHub>();

This documentation however is only valid for the 0.4.0 build of SignalR you would get from nuget – the latest version establishes the IConnectionManager from another means

IConnectionManager connectionManager = Global.Connections;

The resulting code for the ProcessRequest is as follows

public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/plain";

    IConnectionManager connectionManager = Global.Connections;
    dynamic clients = connectionManager.GetClients<SharePointHub>();

    var payload = new
    {
        TasksOpenedToday = context.Request.Params["TasksOpenedToday"],
        TasksCompletedToday = context.Request.Params["TasksCompletedToday"],
        LightStatus = context.Request.Params["LightStatus"]
    };

    JavaScriptSerializer jss = new JavaScriptSerializer();
    var payloadJSON = jss.Serialize(payload);
    clients.addMessage(payloadJSON);
}

Step 3: Create the Event Receiver

There’s nothing particularly fancy going on here aside from posting to our HTTP handler we created in step 2. The rest of the code is just a simple event receiver bound to a task list. If you need help at this step then take a look at Walkthrough: Deploying a Project Task List Definition. We’ll need to override the ItemAdded, ItemUpdated and ItemDeleted events and add the following code

Broadcast(getPayload(properties));

private string getPayload(SPItemEventProperties properties)
{
    SPList list = properties.List;
    SPQuery query = new SPQuery();
    query.Query = "<Where><Eq><FieldRef Name='Created' /><Value Type='DateTime'><Today /></Value></Eq></Where>";
    SPListItemCollection items = list.GetItems(query);
    double tasksOpenedToday = items.Count;

    double tasksCompletedToday = 0;
    foreach (SPListItem item in items)
    {
        if (item["Status"].ToString() == "Completed") tasksCompletedToday++;
    }

    string colour = "RED";
    int percentage = (int)Math.Floor(tasksCompletedToday / tasksOpenedToday * 100);
    if (percentage >= 70) colour = "GREEN";
    else if (percentage >= 50) colour = "ORANGE";

    return string.Format("?TasksOpenedToday={0}&TasksCompletedToday={1}&LightStatus={2}",
        tasksOpenedToday.ToString(),
        tasksCompletedToday.ToString(),
        colour);
}

private void Broadcast(string Payload)
{
    WebRequest request = HttpWebRequest.Create(string.Concat("http://server:port/SharePointRProxyHandler.ashx",Payload));
    WebResponse response = request.GetResponse();
}

Step 4: Create the Web Part

We’re on the home stretch. We’ve got an event receiver posting data to an HTTP handler, which is in turn broadcasting that via SignalR. The only thing left to do is create the client to listen out for that broadcast. This can essentially be HTML and JavaScript and as such doesn’t really need to be a web part at all, but I’ll be creating a visual one in the interests of effective deployment.

It’s here that we need to think back to when we retrieved the latest files from Github for SignalR. You’ll now need to grab the latest JavaScript files from that package and store them in SharePoint so we can reference them in our web part. You’ll also need to grab and store Knockout.

There’s a few differences you’ll need to consider compared to the generic example provided for implementing the SignalR client for hub communication. Firstly, instead of referencing /signalr/hubs in your script src, you’ll need to reference it in the location in which it exists

<script src="http://server:port/signalr/hubs" type="text/javascript"></script>

Secondly, you’ll need to force jQuery to support cross-site scripting

jQuery.support.cors = true; //force cross-site scripting

Third, your hub URL will also need to point to the relevant location

$.connection.hub.url = 'http://server:port/signalr';

Your Hub name will need to be in camel-case (which isn’t clear in the example seeing it’s all lower case)

var sharePointHub = $.connection.sharePointHub;

Your client handler will need to parse the JSON sent in seeing it’s not a simple string

sharePointHub.addMessage = function(json) {
var data = JSON.parse(json);
};

And finally you’ll need to pass a couple of options into the call to start the connection to your Hub

$.connection.hub.start({ transport: 'longPolling', xdomain: true });

That pretty much covers it. Add in some initial population of the viewModel server side and the necessary Knockout bindings and the web part is ready to be deployed. You can see the final web part (minus the basic server side population of variables) below

<style type="text/css">
    .dashboard-item { margin-bottom: 10px; }
    .dashboard-label { font-weight: bold; }
    #LightStatus { width: 50px; height: 50px; }
    .RED { background-color: Red; }
    .ORANGE { background-color: Orange; }
    .GREEN { background-color: Green; }
</style>

<script src="/SiteAssets/jquery-1.7.min.js" type="text/javascript"></script>
<script src="/SiteAssets/json2.min.js" type="text/javascript"></script>
<script src="/SiteAssets/jquery.signalR.min.js" type="text/javascript"></script>
<script src="/SiteAssets/knockout-2.0.0.js" type="text/javascript"></script>
<script src="http://server:port/signalr/hubs" type="text/javascript"></script>

<div class="dashboard-item"><span class="dashboard-label">Tasks Opened Today: </span><span data-bind="text:tasksOpenedToday"></span></div>
<div class="dashboard-item"><span class="dashboard-label">Tasks Completed Today: </span><span data-bind="text: tasksCompletedToday"></span></div>
<div id="LightStatus" data-bind="attr: { class: lightStatus }"></div>

<script type="text/javascript">
    var viewModel = {
        tasksOpenedToday: ko.observable(),
        tasksCompletedToday: ko.observable(),
        lightStatus: ko.observable()
    };

    $(document).ready(function () {
        jQuery.support.cors = true; //force cross-site scripting

        $.connection.hub.url = 'http://server:port/signalr';

        // Proxy created on the fly
        var sharePointHub = $.connection.sharePointHub;

        // Declare a function on the chat hub so the server can invoke it
        sharePointHub.addMessage = function (json) {
            // Update viewModel values here
            var data = JSON.parse(json);
            viewModel.tasksOpenedToday(data.TasksOpenedToday);
            viewModel.tasksCompletedToday(data.TasksCompletedToday);
            viewModel.lightStatus(data.LightStatus);
        };

        //Populate viewModel via ASP.NET and bind to Knockout
        viewModel.tasksOpenedToday("<%= InitialTasksOpenedToday %>");
        viewModel.tasksCompletedToday("<%= InitialTasksCompletedToday %>");
        viewModel.lightStatus("<%= InitialColour %>");
        ko.applyBindings(viewModel);

        // Start the connection
        $.connection.hub.start({ transport: 'longPolling', xdomain: true });
    });
</script>

So how does it look in the end? You be the judge..

So there you have it. I’d be surprised if there’s anyone out there that didn’t think this was pretty awesome. With any luck this will inspire you to go forth and make your own SharePoint implementations with SignalR – I’m looking forward to seeing what will be achieved with this excellent technology. Already Elliot has taken up the challenge to bring Bil’s ‘April Fools’ concept to life, it’s the kind of inspiring functionality that makes you want to go out and experiment. Just one last note – for anyone fearful of how this somewhat new technology would go in an enterprise environment, take a look at the video C#5, ASP.NET MVC 4, and asynchronous Web applications.

How I passed 70-573

Today I sat and passed exam 70-573 – TS: Microsoft SharePoint 2010, Application Development. That means I now officially have the certifications of MCTS: SharePoint 2010, Application Development and MCPD: SharePoint Developer 2010. It may seem a little strange that I did the exams in the wrong order, but there was a method to the madness. Primarily it was to do with the requirement of attaining gold partnership with Microsoft which required the PRO exams to be completed – hence that took priority.

The difference in difficulty between the two developer exams was quite significant – but I guess that’s to be expected. There seemed to be far less ‘gotchya’ questions that needed a sharp eye to weed out the incorrect answers, and more that you just knew. I still ended up putting in a fair amount of study – probably half as much as I did for the 576 exam – but in hindsight I don’t think I even needed that much. Still, the main benefit you get from sitting these exams is solidifying the knowledge you already have and increasing your breadth of knowledge via the study required to pass.

This post will be shorter than my previous one simply because I used less resources. If you want a wider selection of materials you can use to study to pass both exams (including hands-on labs and tutorials) then take a look at my post How I passed 70-576.

Due to the success I had with my previous study method I decided to take the same approach. This involved tracking down a site which would conveniently link me off to all the various MSDN and TechNet resources I would need to read to study each individual element of the exam. It didn’t take long to find one – a quick search for 70-573 delivers you to Becky Bertram’s post SharePoint Exam 70-573 Study Guide with the second result, which was exactly what I was after. While some of the topics linked off to even more, and some of the content could be considered overkill for this exam, it was still a valuable process to undertake.

The second part to my study was re-viewing the exam-cram video series by Ted Pattison and I can’t stress enough how helpful that was. It surprised me a little sitting the exam immediately after watching the 3 parts of the series that were relevant to 70-573 – he literally hands you the answers to a bunch of questions in the exam. In case you don’t feel the need to view my 70-576 post here are the relevant links you’ll need:

Cram Session Part 1
Cram Session Part 2
Cram Session Part 3

And that pretty much sums it up. I’ve been back in the MOSS world for a while now at my current client with minimal exposure to 2010 but still had no troubles with this exam. If you’ve had a bit of experience with 2010, have learnt a bit about the new development features and done a little bit of study on the topics being covered, you should have no troubles at all passing this one.

Once again, Good luck!

Using the Content Query Web Part and jQuery to create a staff desk locator

I recently took it upon myself to provide an alternative to the staff desk locator that was due to go to production in the near future. The back-story is that a requirement existed to locate staff on a floor map to assist with the move to a new office complex. The original concept was created by another developer, but with multiple requirement changes and multiple developers tweaking the original solution, the end result was far from perfect. It only worked completely in IE7 standards browser mode and some of the functionality performed in a less than ideal fashion – think scroll bars to navigate around a zoomed in map amongst other imperfections.

Now the solution I present here is also far from perfect, I have no illusions about that. I debated whether to post about it at all until I had a chance to optimse and refine it seeing that what exists here is essentially a protoype, however I believe it is in a complete enough state to provide some benefit or interest to people out there. If anyone can propose some better ways of achieving some of the functionality demonstrated here I’d be more than interested in hearing it. The first half of the post will explain the journey, so if you’re not interested in what drove the implementation decisions along the way, feel free to skip down to the solution.

The Journey

The concept I was going for was something similar to Google Maps; your standard zoom, move, mouse-wheel and drag functionality. The most attractive option I could find was a paid solution called MapBox which can be seen in their various featured map demos. I didn’t think a paid solution would be an option and besides, I wanted to see if I could create something similar myself. I found a jQuery plugin also called MapBox documented at Mapbox: Zoomable jQuery Map Plugin which definitely appeared to get me half way there. The only remaining challenge was to plot the points on the map and get it driven via SharePoint.

Plotting the points definitely proved challenging. I went through a few iterations as I lead myself down some wrong paths – the joys of experimentation. I went so far as to get everything adjusting correctly from a movement point of view (thinking I was better off starting easy and leaving the complicated functionality for later) only to have it breaking during zoom. It wasn’t until I further investigated the zoom requirements and changed the way in which I was approaching the challenge that I realised the work I had done to adjust for movement was redundant and was handled by the plugin. Lovely.

I eventually got the locations remaining in place during zooming however this exposed its own issues; the pins representing each location didn’t adjust in size as the map did, resulting in a very strange looking experience. It is here where my solution is least elegant – I essentially created multiple CSS classes and multiple sized images and dynamically changed the class of the elements as I zoomed in and out (using the width of the parent div to differentiate). I couldn’t simply scale the image as I was using background images and divs rather than image elements (for reasons based on issues with the previous solution and brief experimentation in this one). This exposed even more gotchyas – it appears different browsers round decimal values in different ways (there were variations around rounding, floor or ceiling). I also noticed that while on most occassions the plugin would zoom to fixed width sizes, occassionally it would result in completely unexpected values which I needed a safety net CSS definition for. I love Internet Explorer. The CSS is hence a pretty ugly beast, but for the most part it works.

The next step was adding some hover over functionality to display the staff members information. This was relatively simple and just leveraged the onMouseOver event and some jQuery for each plotted element. The search functionality was a little more complex. I had witnessed the functionality I desired during my research, present on the Rock ‘n’ Roll Metro Map, which I dug deeper into and discovered it was being achieved via the animate function of the jQuery UI plugin. A couple of equations and experimentation later to determine how I could establish my scroll-to points and it was all humming along nicely.

The final challenge was getting it all into SharePoint. This functionality was to sit on the intranet which had been created as a codeless solution, therefore rather than rendering what I needed via the API in a web part I decided to stick with the theme and leverage the Content Query Web Part (CQWP), drawing out of a custom list. The previous solution had done the same so it wasn’t too difficult with a few tweaks to achieve what I desired. A couple of the gotchyas encountered included ensuring the CommonViewFields were set in the CQWP (exporting and importing the web part was used to achieve this) and rediscovering that for a column to exist to filter on in the web part it needed to be a site column, not just a list column. One last little hurdle that needed to be jumped included how the parts sat on the page with the master page being used – and this differed between browsers (Did I mention how much I love IE?). Seeing this probably had a lot to do with the custom master page being used I’ll leave the specifics out in the solution below, however just know that it is something that may need to be considered.

The Solution

Part 1: The list to hold the data

This was a custom list with some custom columns. Note that the IsAResource column is a site column. The -1000 X and Y values reflect a staff member that does not exist in the building.

Part 2: Header.xsl

The templates in Header.xsl map to the Group Style settings selected in the Content Query Web Parts. They render once to open and close the items which are rendered in between. The below templates were defined.

  <xsl:template name="DeskfinderSelectName" match="*[@GroupStyle='DeskfinderSelectName']" mode="header">
    <script type="text/javascript">document.write('<![CDATA[<div id="SearchByName"><span class="SearchLabel">Search by Name:</span><select onchange="FindUser(this.value);"><option value="">Please select an option...</option>]]>')</script>
  </xsl:template>
  <xsl:template name="DeskfinderSelectNameClose" match="*[@GroupStyle='DeskfinderSelectName']" mode="footer">
    <script type="text/javascript">document.write('<![CDATA[</select></div>]]>')</script>
  </xsl:template>
  <xsl:template name="DeskfinderSelectResource" match="*[@GroupStyle='DeskfinderSelectResource']" mode="header">
    <script type="text/javascript">document.write('<![CDATA[<div id="SearchByResource"><span class="SearchLabel">Search by Resource:</span><select onchange="FindUser(this.value);"><option value="">Please select an option...</option>]]>')</script>
  </xsl:template>
  <xsl:template name="DeskfinderSelectResourceClose" match="*[@GroupStyle='DeskfinderSelectResource']" mode="footer">
    <script type="text/javascript">document.write('<![CDATA[</select></div>]]>')</script>
  </xsl:template>
  <xsl:template name="DeskfinderPin" match="*[@GroupStyle='DeskfinderPin']" mode="header">
    <script type="text/javascript">document.write('<![CDATA[<div class="StaffLocations">]]>')</script>
  </xsl:template>

The most important part to note here is that the DeskfinderPin doesn’t have an associated footer. This was a bit of a gotchya – the browsers closed off the div anyway but if I included the footer, the

<script type="text/javascript">document.write('<![CDATA[</div>]]>')</script>

node was appearing within the div which caused issues when I went to extract the HTML via jQuery and pump it into other locations. It worked fine without the footer so it was removed.

Part 3: ItemStyle.xsl

The templates in ItemStyle.xsl map to the Item Style settings selected in the Content Query Web Parts. They’re rendered for each item in the query. The below templates were defined.

  <xsl:template name="DeskfinderSelectOption" match="Row[@Style='DeskfinderSelectOption']" mode="itemstyle">
    <xsl:variable name="DisplayTitle">
      <xsl:call-template name="OuterTemplate.GetTitle">
        <xsl:with-param name="Title" select="@Title"/>
        <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
      </xsl:call-template>
    </xsl:variable>
    <option value="{@ID}">
      <xsl:value-of select="$DisplayTitle"/>
    </option>
  </xsl:template>
  <xsl:template name="DeskfinderPin" match="Row[@Style='DeskfinderPin']" mode="itemstyle">
    <xsl:variable name="DisplayTitle">
      <xsl:call-template name="OuterTemplate.GetTitle">
        <xsl:with-param name="Title" select="@Title"/>
        <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="starts-with(@Location,'L2')">
		<div class="pin2" style="left:{@X}px; top:{@Y}px;" onMouseOver="DisplayDetails(this);" data-id="{@ID}" data-xpos="{@X}" data-ypos="{@Y}" data-name="{$DisplayTitle}" data-phone="{@Phone}" data-email="{@Email}"></div>
      </xsl:when>
      <xsl:otherwise>
        <div class="pin3" style="left:{@X}px; top:{@Y}px;" onMouseOver="DisplayDetails(this);" data-id="{@ID}" data-xpos="{@X}" data-ypos="{@Y}" data-name="{$DisplayTitle}" data-phone="{@Phone}" data-email="{@Email}"></div>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

It is important to note that all of the custom columns referenced in the template (X, Y, Email, Phone) need to appear in the CommonViewFields element of the Content Query Web Part to be recognised. This can be done by exporting the web part, manually editing the .webpart file to add those columns and importing it back onto the page.

Part 4: The resources

CSS – the CSS used was extended from that used for the MapBox demo with some slight tweaks to those definitions. A little more was added to style the drop down menus and staff information. The majority of CSS was to style the pins mapping to the locations of staff members. As mentioned before, this was a very bloated solution and far too much to include in this post. I’ll try and summarise.

There were essentially 4 groups of styles – level 2 pins, level 3 pins, level 2 ‘located’ pins and level 3 ‘located’ pins. These were seperated into whether they appeared in the firstLayer, secondLayer, thirdLayer or fourthLayer. They were further seperated into sizes mapping to the width of the parent div (the reason for 2 sizes 1 pixel apart is due to the rounding issue I mentioned earlier). Here are a few randomly selected examples:

#firstLayer .pin2
{
	position: absolute;
	width: 10px;
	height: 9px;
	background: url(../PublishingImages/pin2-size709.gif);
}

#secondLayer .pin2.found.size974, #secondLayer .pin2.found.size975
{
	width: 16px;
	height: 16px;
	background: url(../PublishingImages/found2-size975.gif);
}

#fourthLayer .pin3 {
	position: absolute;
	width: 30px;
	height: 27px;
	background: url(../PublishingImages/pin3-size2126.gif);
}

#fourthLayer .pin3.size1505, #fourthLayer .pin3.size1506 {
	width: 21px;
	height: 19px;
	background: url(../PublishingImages/pin3-size1506.gif);
}

You get the idea. Perhaps look into an alternative solution!

Images – The images included the 4 different sized floor map images, the map control image and 100 different pin images to match the CSS styles.

JavaScript – The javascript leveraged that provided with the MapBox demo with the following adjustments.

Functionality to populate the staff information:

function DisplayDetails(person)
{
	$("#staffName").text($(person).attr("data-name"));
	$("#staffPhone").text($(person).attr("data-phone"));
	$("#staffEmail").html('<a href="mailto:' + $(person).attr("data-email") + '">' + $(person).attr("data-email") + '</a>');
}

Functionality to find a given user or resource:

function FindUser(id)
{
	var limitX = 0, limitY = 0, mapWidth = $(".mapwrapper").width(), mapHeight = $(".mapwrapper").height(),
	nodeWidth = $(".current-map-layer").width(), nodeHeight = $(".current-map-layer").height();

	if(mapWidth < nodeWidth) limitX = mapWidth - nodeWidth;
	if(mapHeight < nodeHeight) limitY = mapHeight - nodeHeight;

	var element = $(".current-map-layer div[data-id='" + id + "']");
	var left = (parseInt($(element).css("left")) * -1) + (parseInt($(".mapwrapper").css("width")) / 2);
	var top = (parseInt($(element).css("top")) * -1) + (parseInt($(".mapwrapper").css("height")) / 2);

	left = (left > 0) ? 0 : left;
	left = (left < limitX) ? limitX : left;
	top = (top > 0) ? 0 : top;
	top = (top < limitY) ? limitY : top;

	var width = parseInt($(".current-map-layer").css("width"));
	if ($("div[data-id='" + id + "']").attr("class").indexOf("pin2") == -1)
		$("div[data-id='" + id + "']").attr("class", "pin3 found size" + width);
	else
		$("div[data-id='" + id + "']").attr("class", "pin2 found size" + width);

	$(".current-map-layer").animate({top: top,left: left}, {easing: "easeOutQuart"});
	DisplayDetails(element);
}

The important thing to note here is that extra code was required to ensure the map wasn’t moved ‘out of viewport’. Thankfully, the MapBox JavaScript already included that logic for its drag functionality so I just leveraged that.

Document Ready functionality:

$(document).ready(function() {
	$("#firstLayer,.mapcontent").html($(".StaffLocations").html());

	$("#viewport").mapbox({
		mousewheel: true,
		layerSplit: 8//smoother transition for mousewheel
	});
	$(".map-control a").click(function() {//control panel
		var viewport = $("#viewport");
		//this.className is same as method to be called
		if(this.className == "zoom" || this.className == "back") {
			viewport.mapbox(this.className, 2);//step twice
		}
		else {
			viewport.mapbox(this.className);
		}
		return false;
	});
})

The first line is the most important – this is where the HTML is taken from the hidden div rendered by our Content Query Web Part and injected into the necessary locations. The rest of the code is the same that existed for the MapBox demo.

Custom changes to the _zoom function (insert above return movement; line)

/* Custom changes */
var xChange = (totalWidth == undefined) ? 1 : totalWidth / $("#firstLayer").width();
var yChange = (totalHeight == undefined) ? 1 : totalHeight / $("#firstLayer").height();

$(".pin2,.pin3").each(function(index, value) {
	$(this).css("left", ($(this).attr("data-xpos") * xChange));
	$(this).css("top", ($(this).attr("data-ypos") * yChange));

	var width = parseInt($(".current-map-layer").css("width"));
	if ($(this).attr("class").indexOf("pin2") == -1)
	{
		if ($(this).attr("class").indexOf("found") == -1)
			$(this).attr("class", "pin3 size" + width);
		else
			$(this).attr("class", "pin3 found size" + width);
	}
	else
	{
		if ($(this).attr("class").indexOf("found") == -1)
			$(this).attr("class", "pin2 size" + width);
		else
			$(this).attr("class", "pin2 found size" + width);
	}
});
/* End Custom changes */

Part 5: Referencing the resources

This was a chromeless Content Editor Web Part referencing the required resources:

<link href="../Documents/master.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<script type="text/javascript" src="../Documents/mousewheel.js"></script>
<script type="text/javascript" src="../Documents/mapbox.js"></script>

Take note the version of jQuery referenced – it’s not the latest, but was required for MapBox to function correctly.

Part 6: The search box

This was a chromeless Content Query Web Part pointing to the list in Part 1. It was set to show items of type ‘Custom List’ and filtered where ‘IsAResource is equal to 0’. The Presentation was grouped by <Site> (to ensure the group element was rendered) and sorted by ‘Title ascending’. The ‘Limit the number of items to display’ was turned off. The Group Style was set to ‘DeskfinderSelectName’ and Item Style set to ‘DeskfinderSelectOption’.

To include a Search by Resource box as well as a Search by Name box, the steps above can be followed, however the filter value should be 1 and the Group Style should be set to ‘DeskfinderSelectResource’.

Part 7: The map, associated controls and staff information

This was a chromeless Content Editor Web Part which essentially rendered the HTML which existed in the MapBox demo with a few minor tweaks.

<div class="mapwrapper">
	<div id="viewport" style="overflow: hidden; position: relative;">
		<div id="firstLayer" class="current-map-layer" style="background: url('Images/FloorImage1.png') no-repeat scroll 0% 0% transparent; width: 709px; height: 631px; position: absolute; display: block; left: 0px; top: 0px;">
		</div>
		<div id="secondLayer" style="height: 947px; width: 1063px; position: absolute; display: none;">
			<img style="width: 100%; position: absolute; left: 0pt; top: 0pt;" src="Images/FloorImage.png" alt="">
			<div style="position: absolute; left: 0pt; top: 0pt; background: none repeat scroll 0% 0% white; opacity: 0;" class="map-layer-mask"></div>
			<div style="position: absolute; top: 0pt; left: 0pt;" class="mapcontent">
			</div>
		</div>
		<div id="thirdLayer" style="height: 1262px; width: 1417px; position: absolute; display: none;">
			<img style="width: 100%; position: absolute; left: 0pt; top: 0pt;" src="Images/FloorImage.png" alt="">
			<div style="position: absolute; left: 0pt; top: 0pt; background: none repeat scroll 0% 0% white; opacity: 0;" class="map-layer-mask"></div>
			<div style="position: absolute; top: 0pt; left: 0pt;" class="mapcontent">
			</div>
		</div>
		<div id="fourthLayer" style="height: 1893px; width: 2126px; position: absolute; display: none;">
			<img style="width: 100%; position: absolute; left: 0pt; top: 0pt;" src="Images/FloorImage.png" alt="">
			<div style="position: absolute; left: 0pt; top: 0pt; background: none repeat scroll 0% 0% white; opacity: 0;" class="map-layer-mask"></div>
			<div style="position: absolute; top: 0pt; left: 0pt;" class="mapcontent">
			</div>
		</div>
	</div>
	<div class="map-control">
		<a href="#left" class="left">Left</a>
		<a href="#right" class="right">Right</a>
		<a href="#up" class="up">Up</a>
		<a href="#down" class="down">Down</a>
		<a href="#zoom" class="zoom">Zoom</a>
		<a href="#zoom_out" class="back">Back</a>
	</div>
	<div class="staff-information">
		<div><span class="staff-info-label">Name: </span><span id="staffName"></span></div>
		<div><span class="staff-info-label">Phone: </span><span id="staffPhone"></span></div>
		<div><span class="staff-info-label">Email: </span><span id="staffEmail"></span></div>
	</div>
</div>

Note that the images and sizes were adjusted respectively and each layer div was given an id so I could reference them via both jQuery and CSS. The staff-information div was also included to present the staff information.

Part 8: The staff locations

This was a chromeless Content Query Web Part pointing to the list in Part 1. It was set to show items of type ‘Custom List’, grouped by <Site> and the ‘Limit the number of items to display’ was turned off. The Group Style was set to ‘DeskfinderPin’ and Item Style set to ‘DeskfinderPin’.

Note that the contents rendered here were within a div hidden by the CSS – it’s main purpose was to render the data once, then jQuery injected it into the locations required.

The End Result

An image doesn’t really do it justice, but for the purposes of completing the article, the end result looks something like that depicted below.

Either that or you can watch a video below on how the functionality works.

How I passed 70-576

I had the good fortune today to sit, and thankfully pass, exam 70-576 – PRO: Designing and Developing Microsoft SharePoint 2010 Applications. Aside from the fact the computer tried to tell me I was a no-show even after turning up half an hour early, it all went rather smoothly.

I’ve had a bit of experience sitting the Microsoft exams in the past. Going back as far as June 2008 sitting the core .NET and Winforms exams and then moving on to 3 of the 4 2007 SharePoint exams in 2009/2010, so I figured I kind of knew what to expect. This is probably the most amount of study I’ve put into a cert as well and as such I’ve learnt more than I ever have before – definitely the main benefit you get out of sitting the exam is the amount of content you learn to pass it.

But anyway, back to the point. I discovered a lot of different valuable resources that assisted me along the way to passing this exam. A few I didn’t end up getting to but i’ll include them anyway for the sake of completeness – they may come in handy.

Blogs: Rather than create these types of posts which was my original intention, I thankfully found some existing blogs that covered off what I wanted – namely breaking down the exam into it’s components and either explaining or linking off to MSDN/Technet content. The most useful I found was Martin Bodocky’s set of posts but beware – it’s definitely not for the short of time. This formed the majority of my study, and while the content could be found on MSDN/Technet directly – his posts saved me a lot of time!

Another blog I read towards the start was Pedro Pinto’s guide to the exam – it covered a reasonable amount of content and would be more attractive to those short on time or allergic to constant link-clicking in MSDN.

Training and Labs: Admittedly I never got to any of this content. I would eventually like to, but time didn’t permit. As it turned out, I didn’t really need it to pass the exam – but i’m sure it would suit those more inclined to hands-on learning rather than reading.

Videos: Now this is where I struck gold. Watched all of these and they were well worth it. The exam-cram series by Ted Pattison is a must see – shout out to my colleague Elliot Wood for tracking them down.

That about covers it. I’ll sign off with a bit of my own advice. Read the questions carefully – very carefully. Use process of elimination – there will be the obvious 1 or 2 incorrect answers but more important to see is (on some occassions) the 1 word in the question that makes all the difference to the answer. If you want advice on how to pass 70-573 then take a look at my post How I passed 70-573.

Good luck!