I haven’t talked much about Yammer here, but we’re using it pretty extensively at Trek. Definitely a game changer if used correctly and often. The best part is that Yammer integrates with SharePoint, but one feature missing is that of auto posting to Yammer. While manual posting to Yammer is there, and it works pretty slick, the absence of any programmatic posting causes a barrier to adoption with some of our groups.
Originally we attempted to accomplish this via a custom SharePoint Designer Action. Seemed like the most reasonable approach to try first. We scoped it as a sandbox solution, which forced us to do a full-trust proxy since we were using email as our delivery vehicle. Needless to say, the attempt failed. Partly because of Yammer’s issues with email feature. Things got so bad for Yammer they had to re-architect their whole approach to e-mailing. So we shelved the idea.
Fast forward a few months. Email to Yammer is working and a few groups were pushing for the functionality we had tried a few months back. Sat down with Tim and tried to logically architect this. What to do? Object model, SSIS package, Event Receiver, OData? Lots of options but which one is the best? I kept on my old path of trying to use SharePoint tools to solve this so I traveled down the client object model path. Why? Because it sounds cool.
Long story short: Epic. Fail.
Client Object Model – in this case – just isn’t really good at grabbing the Created By’s email address and plugging it into an email. But the bigger issue though was that I was focused on the solution and not the problem. Lesson learned here: when developing code, the goal should be to remove as many external dependencies as possible. The object model puts a big, fat dependency on SharePoint’s code and could possibly come back to haunt me in the future. Enter OData. Developed by Microsoft, it’s a standard data access method that isn’t going anywhere for the foreseeable future. Sweet.
Next I had to figure out how to flag items for processing and then – once processed – how do I flag it so that the app knows never to process it again. Enter custom columns and content types. Enable control of content types in your list and add 2 choice columns: SendToYammer and Processed. The choices are Yes and No. I originally tried a Yes/No column but it appears the data types are different between the two types of columns. I set the defaults on both columns to No. I then hid the Processed column in the content type so that only the app would have access to it.
Now that the SharePoint List is where I want it. Time to open up Visual Studio. I referenced Eric White’s blog to get me started: http://blogs.msdn.com/b/ericwhite/archive/2010/12/09/getting-started-using-the-odata-rest-api-to-query-a-sharepoint-list.aspx
- Create a new project. Click File -> New -> Project. Select a directory for the project. Set the name of the project to PostToYammerOData.
- Right click on the References node in the Solution Explorer window, and click Add Service Reference. Enter http://site/_vti_bin/listdata.svc for the address. Change the namespace to PostToYammer.
Now for the code – apologies in advance for not posting the “cleanest” code, but hey, it works:
static void Main(string args)
//You can get the DataContext when you setup the Service Reference
[Title of your site]DataContext dc = new [Title of your site]DataContext(new Uri("http://site/_vti_bin/listdata.svc"));
dc.Credentials = CredentialCache.DefaultNetworkCredentials;
var result = from d in dc.[List Title]
where d.SendToYammerValue == "Yes" && d.ProcessedValue == "No"
//Define your columns
Id = d.Id,
Subject = d.Title,
Body = d.Body,
//may be .Email or .WorkEmail depending on your AD attribute mappings
CreatedByEmail = d.CreatedBy.EMail
foreach (var d in result)
//For Troubleshooting purposes
// email to yammer
string to = "[Yammer group address]";
string from = d.CreatedByEmail;
MailMessage message = new MailMessage(from, to);
message.Subject = d.Subject;
message.Body = d.Body;
SmtpClient smtp = new SmtpClient();
smtp.Host = "[Exchange IP address]";
smtp.Port = [port];
// update by id, set processed to yes
var item = dc.[List Title]
.Where(i => i.Id == d.Id)
item.ProcessedValue = "Yes";
Basically the code opens the list, iterates through the list’s items and – for each item where SendToYammer is equal to “Yes” – e-mail Yammer then set the Processed column to “Yes.”
I can take my newly built and tested code and I can give it to someone to run on their desktop or I can deploy it to a Windows Server in my environment and use Task Scheduler to run the app on a scheduled basis. We chose the latter. Just make sure whoever runs the app (or if you use a Service Account like we did) has Contribute rights to the site.
All the lists I’ve attempted this with have had less than a few hundred items. I haven’t tried it with 1000 or more and we know that in some instances OData will only return 1000. Check out Tim’s post on how he overcame that issue (Link).
One last thing, why didn’t I use an Event Receiver? Well, besides the dependencies mentioned above, I can never get Event Receivers to work. Then again I try to do sandbox whenever possible which could be part of my problem and if you want to e-mail with a sandbox solution you’ll need a Full Trust Proxy, thereby defeating the purpose of a sandbox solution.
Thanks again to Tim and especially Steve for giving me a hand on this. Much appreciated.