The benefits of Microsoft SharePoint Software Development Kit (SDK)

I would like to take this moment to thank Microsoft for doing a ton of work to get me to be able to work all the time, even when I am offline. No matter if I am on vacation, sitting on the bus, relaxing in a Coffee shop, I can always work.

My wife also thanks you. I could translate her exact words but I am afraid I will get banned for being an overly offensive site.

I would like to share my thoughts on one of the best "work anywhere, anytime" products that Microsoft has provided.

The Microsoft SharePoint Software Development Kit (SDK)

Now, I know this SDK will be very well known for most SharePoint developers. I also know that most SharePoint developers are online most of the time. I also know that MSDN has a wonderful up-time history. So, most of the time you can use the online version and get loads of more information, as well as community content, which is really great.

However, when you are not online or something has happened to MSDN, the SharePoint SDK is a great tool. I have previously written about why CAML is the foundation of any good SharePoint developer, and that CAML training should be a requirement in kindergarten. Learning CAML makes you understand all those strange config files that SharePoint utilizes, such as onet.xml, schema.xml, feature.xml, and others. At least it will help you build them and read the general purpose of one of those files. But what does the SourceId of a site column field really do?

The SDK contains all the CAML references you need and will happily answer this for you:

SPField.SourceId Property:

Gets the namespace that defines the field or the GUID of the list in which the custom field has been created through the user interface.

Try figuring that out by reading features and onet, I dare you! Ok, it may not be that difficult if you know what you are seeking, but the SDK helps a whole lot. And the best thing, it is available offline so when you are on that extremely remote mountain top and the only way down is to explain to someone what SourceId really means, well, flip up your laptop, open the SDK and look it up.

And this applies to a lot of other things as well, not just CAML. There are a bunch of namespaces in addition to the standard Microsoft.SharePoint namespace. A wealth of information about the SharePoint object model (OM) is at your fingertips. Not to mention the richness of the SharePoint web services and the, I must say, impressive amount of information that is readily available regarding the dos and don’ts of SharePoint development.

Content migration, the bane of many a SharePoint deployment, has a section that answers and gives example for several really useful scenarios such as migrating a web site from one location to another. Perhaps not perfect, content migration is really powerful, especially now that a lot of the critical bugs were fixed in the recent SharePoint infrastructure upgrade.

I can go on to list a whole array of other useful stuff that you get in the SDK, but suffice to say, you should never have to be bored again if you find yourself offline and yo ustill have your latop.

What’s missing and what’s wrong with the SDK?

What I miss, though, and I realize this would have put a ton of extra megabytes to the download, is the videos, or Visual How Tos as they are called. I absolutely hate that the videos are not easily downloadable. There is also approximately 2 technical articles altogether, so there is a really serious lack of content. I know, there are far more articles, but way to few. This has improved a bit in version 1.3, and they have even included a few excerpts from the excellent book Inside Microsoft Windows SharePoint Services 3.0 that I highly recommend, but still, the technical articles part is really lacking in content.

Also the actual packages and installation experience leaves a bit to be desired. First of all, in contrast with most other SDKs you get from Microsoft, in Add/Remove components, the SharePoint SDK is not actually called and SDK, but rather Windows SharePoint Services Developer Resources. And when you want to upgrade from 1.2 to 1.3 of the SDK you are asked to remove the previous installation first. Thinking you want to remove the SDK and look for SharePoint SDK in the list would seem logical, but alas, no. Same thing with 1.3, by the way, still not called SDK, but Windows SharePoint Services Developer Resources 1.3.

The installer for 1.3 also states that it is installing version 1.2 while it is, in fact, installing the right version.

And of course, the same applies online as offline, a lot of the documentation for SharePoint is simply not there. Or anywhere, it seems. Plenty of features are just not documented and Microsoft really needs to do a better job in the next version of the SDK.

The end is near, but salvation is too

The SDK does a great job at bringing valuable content offline. It is great to just sit an browse all the information on your free time. You will never again have an excuse to not work.

You can download the SDK from Microsoft from the online SDK site. The download links are just beneath the tags on that page, in the first Community Content comment.

Just don’t forget to pay attention to your wife. Isn’t that right, dear?

Found this article valuable? Want to show your appreciation? Here are some options:

a) Click on the banners anywhere on the site to visit my blog's sponsors. They are all hand-picked and are selected based on providing great products and services to the SharePoint community.

b) Donate Bitcoins! I love Bitcoins, and you can donate if you'd like by clicking the button below.

c) Spread the word! Below, you should find links to sharing this article on your favorite social media sites. I'm an attention junkie, so sharing is caring in my book!

Pin It

Looking for alternative blogging solution

It seems I’ve come to a cross in the road and I need your advice on which path to take. And to make the deal a bit sweeter I will award the best solution with a $25 eBay gift certificate.

I’ve reached the root of Blogger/blogspot. I need features that I have not found to be available. I am going to describe what I am missing here and hope you can provide me with some advice on which solution, hosted or otherwise, that I should investigate. I have no preference for free or paid services but I need a free, full-featured trial at least.

First of all, and what actually got me started on this track, is the lack of control over HTML. Specifically I wanted to remove some adsense ads and customize them to better blend into the site. Turns out, blogger messes up comments in HTML, effectively removing any chance of controlling the adsense ads. A sub-feature here is that Blogger ads their own adsense ad at the end of the first article, a horrible image ad that I hope no-one will miss.

Second I want more interaction with you guys. I want better comments options, preferably anonymous with some captcha or similar to prevent spam. I want ping backs or something similar so I can keep in touch. Perhaps a forum of some sorts. Could be extremely simple, I don’t need anything fancy.

Third I want hosting on my own domain. I’ve registered a domain name to host content already. I would like to add some non-blog pages, such as a better index of my SharePoint articles. Better means better than tag clouds, keyword search and Google search. I know blogger supports this.

So my feature list is as follows:

– Better control over HTML content, essentially more adsense-friendly markup

– Better visitor interaction

– Custom pages and custom domain

So, which solution do you think I should choose? Write to me at furuknap<[at]>gmail.com or post a comment in this blog. The author of the solution with which I end up will receive a $25 eBay gift certificate as described on http://giftcard.ebay.com/ns/giftcert.html. Solution needs to be submitted by August 31, 2008 and a winner will be announced by September 30, 2008.

EDIT: Seems the image ad was placed there by Feedburner at my own request. I feel really stupid for not noticing this. Its gone now.

Pin It

Send a SharePoint document library file as email

Ever wanted to send a SharePoint item by email to someone? No? Well, neither have I. turns out, someone else did, though, and they did not know how, so I thought I’d help out. And you never know, it might turn out to be you next time, and what will you do then? Now you can just remember that weird Norwegian guy who wrote that thing back in the days and come here to pick up your solution. And, to save you some time, I’ll actually upload the entire solution for you, ready to use with just one simple step to do.

Scope

Ok, so what is our scope. I want to have some way of sending an individual file from a SharePoint library to someone. The file should be sent as an attachment and I should just have to enter the recipients email and perhaps a message.

To accomplish this I want to add a choice to the drop-down menu that appears on a library item when you hover-and-click a library item:

step-1

Clicking on that item should open up a form that I can use to fill out recipient address and a message. When I click a Send button on that page I should return to the list.

Let’s get down to business.

Solution walk-through

For this project I will use WSPBuilder that I wrote about in my Basic setup of SharePoint Visual Studio project article. Make sure you have WSPBuilder with the Visual Studio extensions installed, it will save you tons of work and make SharePoint development a joy. So much for advertising.

Our ingredients:

– One visual studio 2005 or 2008.

WSPBuilder with Visual Studio Extensions.

– SharePoint in any v3 flavor, WSS or MOSS

.Net Reflector

– An SMTP-server, like that of your ISP or your own

Step 1: Setup

First, start by creating a new WSPBuilder project in Visual Studio. Use whatever name you like, for example SendAsEmail as I did. Add a new empty feature to the project. With WSPBuilder extensions it is simply a matter of right-clicking the project in the solution explorer and click Add->New item. The items available to you includes an empty feature. Write a nice description and make sure the feature is web scoped.

Second, add a class file. I like to add my class files to a folder in the Project called FeatureCode. The reason for this is that WSPBuilder will also use this folder to add custom code, and I like to keep my code in one place in small projects such as this. To do so, right-click the project again and click Add->New folder. Call it FeatureCode. Then, right-click that folder and click Add->Class. Browse to the Visual C# Project items to find the Class file. Call it again whatever you like. I call mine SendAsEmail.cs.

Third, add references to your project. Right-click the References in solution explorer and add references to Windows SharePoint Services (microsoft.sharepoint.dll) and System.Web.

Finally, create a new blank ASPX page to your solution. This page will be the custom form we will use to input the recipients email and the message text. To do so, first right-click on the 12\Template folder under your project in the solution explorer. Click Add->New folder and call it Layouts. No, you cannot call this anything else, it must be named Layouts. This folder largely corresponds to the _layouts virtual directory in SharePoint and we want to put our file there to make it available everywhere. Next, right-click the layouts folder and click Add->New item. Again, browse to the Visual C# Project items and find a Text file item. There is no ASPX page item to add to a non-website project, but we can still get one by naming our new text file SendAsEmail.aspx. Or something else, the important thing is to call it [something].aspx.

Now, your solution explorer should look like this, save any differences in naming you have done:

step-2

If your solution does not look like this and you do not know why, retrace your steps to find out what you missed.

Now to start the actual development.

Step 2: Create a custom action feature

Open the empty feature you created in step 1. Browse to the folder in the solution explorer and open the elements.xml file. In the elements.xml file, add the following code:

 

    1 xml version="1.0" encoding="utf-8" ?>
    2 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    3   <CustomAction Title="Send as email"
    4                 Id="SendAsEmailECB"
    5                 RegistrationType="List" 
    6                 RegistrationId="101" 
    7                 ImageUrl="/_layouts/images/MSG16.GIF" 
    8                 Location="EditControlBlock" 
    9                 Sequence="225">
   10       <UrlAction Url="~site/_layouts/SendAsEmail.aspx?ItemId={ItemId}&ListId={ListId}" />
   11   CustomAction>
   12 
   13 Elements>

 

The customaction element allows you to modify action menus all around SharePoint. There are a few lines here that are critical to accomplish what we want. Line 5, RegistrationType, states that we want this to be linked to a list, and line 6, RegistrationId, states that the list type should be from template 101 or Document Library. If you develop your own list templates you can link a custom action to only that particular list by modifying RegistrationId to match you template type. List 8, Location, states that we want to add this to the EditControlBlock. That’s the name of the hover-and-lick menu where we want our custom action to appear.

Inside the CustomActions element we have a URL Action element. That simply tells SharePoint what should happen when we click that link. If you notice the Url-attribute it holds two tokens, ItemId and ListId. these tokens will be filled in for us by SharePoint. Tokens are widely used in SharePoint so I wont go into them in detail here, these two should be self-explanatory. Perhaps I will write an article on tokens one day.

Basically, that’s it for the feature code. If you are using WSPBuilder you can actually build, deploy and activate this feature and the menu item will appear. Of course, we haven’t actually built any code yet, so it will fail miserably. Let’s move on.

Step 3: Create the asp.net page to get input from user

Open the SendAsEmail.aspx page from the Layouts folder. Now, I am extremely far from being a designer, and I believe in separating code from design in any case so I’ll just make this extremely simple design-wise. There are a few things that we will need to do, though.

First, paste the following code into the aspx-file. Make sure you are in code view and not in design view:

<%@ Assembly Name="[STRONG NAME]" %>
<%@ Page Language="C#" MasterPageFile="~/_layouts/application.master"
        Inherits=”NittiTre.SendAsEmail”  %>

Second, get the strong name of your assembly, you need to paste that into where it says [STRONG NAME]. To do so, and I am assuming you are still using WSPBuilder, hit Build (Menu->Build->Build solution). Start up .net Reflector and open your assembly dll, often located in My documents\Visual Studio 2005\Projects\Solutionname\Projectname\bin\debug. At the bottom of reflector you will now see your strong name:

step-3

Simply copy the entire strong name, all four parts. Paste this into the code where it says [STRONG NAME].

You may also need to edit the Inherits-attribute of the Page directive. I have written NittiTre.SendAsEmail since that is the namespace and name of the class I will be writing in the next step.

The page itself is fit into the application.master of the SharePoint site. This master page has a contentplaceholder called PlaceHolderMain in which we put a simple table with a few controls with IDs of lblSendTo, lblMessage, btnSend, txtSendTo and txtMessage. You can basically hand this page over to your designer, but make sure that these IDs remain the same. This is important as we will be wiring up these controls in a code-behind file, and if the IDs do not match we get a runtime exception.

Let’s move over to the code.

Step 4: Write the class to send the email

Finally it’s time to do some coding.

Start by adding a few Using statements to the top to make our code a bit more readable:

    1 using System;
    2 using System.Collections.Generic;
    3 using System.Text;
    4 using System.Web.UI;
    5 
    6 using System.Net.Mail;
    7 using Microsoft.SharePoint;
    8 using Microsoft.SharePoint.WebControls;
    9 using System.Web.UI.WebControls;

Second, make sure your class inherits from LayoutsPageBase and add some controls that will have names matching the IDs of the controls we added on the aspx page. We will also add a few variables to hold our mail server configuration:

   10 
   11 namespace NittiTre
   12 {
   13     public class SendAsEmail : LayoutsPageBase
   14     {
   15 
   16         protected Label lblSendTo;
   17         protected Label lblMessage;
   18         protected Button btnSend;
   19 
   20         protected TextBox txtSendTo;
   21         protected TextBox txtMessage;
   22 
   23         private string mailServer = ""; // YOU NEED TO ADD SOMETHING HERE!
   24         private int mailPort = 25;
   25 

Ensure that you add the host name of your SMTP server in line 23.

See line 11 and 13? The namespace and the name of the class makes up what we should put in the aspx file Page inherits directive.

Since we want to have a button with an event handler we need to make sure that all our controls are created before the event handler wireup completes. A good place to do this is in the OnLoad method, so lets override that:

   26         protected override void OnLoad(EventArgs e)
   27         {
   28             EnsureChildControls();
   29         }
   30 

 

The EnsureChildControls makes sure that CreateChildControls() are called once and only once. If you happen to call EnsureChildControls again later in the code it will not create new child controls thus saving us the trouble of finding out if the controls have been added or not.

If you have ever experience adding event handlers to your controls and having them not fire it is often because you hooked up the event handler too late in the page life cycle. Often, an event handler not firing is because of just that. Simple fix, just call EnsureChildControls in your onload overridden method.

Of course, for CreateChildControls to actually, well, create child controls we need to override that method and make sure we hook up our event handler. I’ve also added a default text to the message box:

   31         protected override void CreateChildControls()
   32         {
   33             btnSend.Click += new EventHandler(btnSend_Click);
   34 
   35             txtMessage.Text = "Hello, this file is sent from SharePoint";
   36         }
   37 

Now for the bulk of our code, the btnSend_Click method that will fire when someone clicks that button. Notice line 33? That is where we hook it up. Now for the code. I’ve written inline comments to describe what is going on rather than commenting afterwards.

   38         void btnSend_Click(object sender, EventArgs e)
   39         {
   40             EnsureChildControls(); // Has been called already, but let's make sure...
   41 
   42             // Find the list and item ids from the querystring
   43             try
   44             {
   45                 Guid listId = new Guid(Server.UrlDecode(Request.QueryString["ListId"]));
   46                 int itemId = int.Parse(Request.QueryString["ItemId"]);
   47 
   48                 // Find our item from the current web
   49                 SPWeb web = this.Web;
   50                 SPListItem item = web.Lists[listId].GetItemById(itemId);
   51 
   52                 // Start building our mail message    
   53                 string senderMail = web.CurrentUser.Email;
   54                 string recipientMail = txtSendTo.Text;
   55                 MailMessage message = new MailMessage(senderMail, recipientMail);
   56                 message.Body = txtMessage.Text;
   57                 message.Subject = item.DisplayName;
   58 
   59                 // Add the file as an attachment
   60                 SPFile file = item.File;
   61                 Attachment attachment = new Attachment(file.OpenBinaryStream(), file.Name);
   62                 message.Attachments.Add(attachment);
   63 
   64                 // ...and finally try sending
   65                 SmtpClient smtp = new SmtpClient(mailServer, mailPort);
   66                 smtp.Send(message);
   67                 Response.Clear();
   68                 Response.Redirect(web.Lists[listId].DefaultViewUrl);
   69             }
   70             catch 
   71             {
   72                 throw;
   73             }
   74         }
   7
5     }
   76 }


Most of this code consists of finding information about the item selected and then start building the mail message from that information along with the input from the form.

Note that I have not added much error handling. This is bad and you should add better error handling code, especially around the SmtpClient.Send method call. A lot of things can go wrong when attempting to send an email to another server. Make sure you at least throw any exceptions up to the user so that they get an error message.

If everything goes according to plan, we send the user back to the list in line 68.

That is it. Nothing more. Let’s build, deploy and activate. I’ve uploaded a zipped solution containing everything as written here. You can download that from here. Do remember to edit your SMTP Server, that should be the only thing you need to do.

Step 4: Deploy

If you have been wise and paid attention you are using WSPBuilder. If so, right click you project in the Solution Explorer, click WSPBuilder->Build WSP. Next, do the same again, and not that now that you’ve built the WSP, more options become available in the menu. Click Deploy. Hang around for a while and your solution will be deployed.

Next, you need to activate your feature. Open your SharePoint site and go to Site Settings. Under web features you will find your SendAsEmail feature. Click activate and your document libraries now gets the new feature of sending a document library item as an attachment.

Finally!

Congratulations, you have created a hopefully useful feature. Go ahead, play around with it. Suggestions for improvements may be:

– Implement sending all documents in a folder at once (hint: folders are simply content types and you can limit the edit control box to only apply to certain content types)

– Look up recipients names in an existing contact list to avoid misspelling names

– Send to multiple recipients

– Add more mail related parameters such as Cc, Bcc, encryption, etc.

– Save user preferences for these parameters

Good luck, and let me know how it turns out.

Pin It