Getting Safe Value From ListItem In Office 365 And SharePoint Online

Reading a ListItem in SharePoint online is nothing fantastic and is pretty similar to reading list items in the throwback server OM models. Consider the below example that starts with a ListItemCollection. We are reading the value of SomeCrap. The problem here is, what if that returns null? That’s an issue.

[csharp]

ListItemCollection items = list.GetItems(CamlQuery.CreateAllItemsQuery());
list.Context.Load(items);
list.Context.ExecuteQuery();
foreach (ListItem item in items)
{
list.Context.Load(item, x => x[“SomeCrap”]);
list.Context.ExecuteQuery();
string someCrap = item[“SomeCrap”].ToString();
}

[/csharp]

There is an easy extension means to handle this though, where instead of null due to the ToString() it will just give the default string.Empty. Here is the extension and an example of its use.

[csharp]

public static T GetSafeValue(this ListItem item, string fieldName) where T : class
{
object o = item[fieldName];
if (o == null || !(o is T))
{
return null;
}
return (T)o;
}

then its use.

[csharp]

foreach (ListItem listItem in items)
{
string someCrap = listItem.GetSafeValue(“SomeCrap”);
}

[/csharp]

Share

Getting The Full, Absolute URL Of A ListItem In Office 365

I don't know why Microsoft made it such a pain in the ass to get the url for most of the proxy objects on the SharePoint server object model, but in Office 365 it is even worse. Here is an example of how to get a ListItem actual URL and the modified date of the item. Following I will throw the values into a dictionary.

[csharp]

Dictionary urlDict = new Dictionary();
foreach (List list in ListsToProcess)
{
ListItemCollection items = list.GetItems(CamlQuery.CreateAllItemsQuery());
list.Context.Load(items);
list.Context.ExecuteQuery();
foreach (SharePointListItem item in items)
{
list.Context.Load(item, x => x["FileRef"], x => x["Modified"]);
string startUrl = list.Context.Url;
list.Context.ExecuteQuery();
string fullUrl = startUrl + item["FileRef"];
string lastModified = item["Modified"].ToString();
if (!urlDict.ContainsKey(fullUrl))
{
urlDict.Add(fullUrl, lastModified);
}
}
}

[/csharp]

Share

Adding Remote Event Receivers To An Exisiting List In Office 365

This is a generic approach in order to add event receivers to an existing list, say at the host or app web level really doesn’t matter. There are a couple of methods that make it nice and clean.

This first part will define a little helper method to build the creation information for the event receiver. Notice you have to specify the remote app url in your manifest tokens.

[csharp]

public static EventReceiverDefinitionCreationInformation BuildGenericEventRecieverWithoutEventType()
{
string remoteAppurl = HttpContext.Current.Request[“RemoteAppUrl”];
string remoteEventEndPointUrl = String.Format(“{0}/PutYourServiceNameHere.svc”, remoteAppurl);
EventReceiverDefinitionCreationInformation eventReceiver = new EventReceiverDefinitionCreationInformation();
eventReceiver.ReceiverName = “GiveYourRevc”;
eventReceiver.ReceiverUrl = remoteEventEndPointUrl;
eventReceiver.SequenceNumber = 5000;
eventReceiver.ReceiverClass = “Fully qualified Path To RER Assembly”;
eventReceiver.ReceiverAssembly = Assembly.GetExecutingAssembly().FullName;
return eventReceiver;
}

[/csharp]

If you are adding or removing a receiver, you of course have to test whether that receiver exists! That’s what the below method does. We just use the class name since that should be unique.

[csharp]

public static bool DoesEventReceiverDefintionExistBasedOnCreationInfo(EventReceiverDefinitionCreationInformation info, List list)
{
bool exists = false;
list.Context.Load(list, x => x.EventReceivers);
list.Context.ExecuteQuery();
foreach (EventReceiverDefinition eventReceiverDefinition in list.EventReceivers)
{
string innerDefId = eventReceiverDefinition.ReceiverClass;
string outerDefId = info.ReceiverClass;
if (innerDefId.Equals(outerDefId, StringComparison.InvariantCultureIgnoreCase))
{
exists = true;
break;
}
}
return exists;
}

[/csharp]

Since the receivers were built without a specific event type, you can specify as many receiver capture behaviors as you want, as demonstrated in the below example.

[csharp]

public static void ApplyEventReceiver(ClientContext context, List list)
{
EventReceiverDefinitionCreationInformation eventReceiver = Helpers.BuildGenericEventRecieverWithoutEventType();
eventReceiver.EventType = EventReceiverType.ItemAdded;
if (!DoesEventReceiverDefintionExistBasedOnCreationInfo(eventReceiver, list))
{
list.EventReceivers.Add(eventReceiver);
}
eventReceiver = BuildGenericEventRecieverWithoutEventType();
eventReceiver.EventType = EventReceiverType.ItemUpdated;
if (!DoesEventReceiverDefintionExistBasedOnCreationInfo(eventReceiver, list))
{
list.EventReceivers.Add(eventReceiver);
}
eventReceiver = BuildGenericEventRecieverWithoutEventType();
eventReceiver.EventType = EventReceiverType.ItemDeleted;
if (!DoesEventReceiverDefintionExistBasedOnCreationInfo(eventReceiver, list))
{
list.EventReceivers.Add(eventReceiver);
}
eventReceiver = BuildGenericEventRecieverWithoutEventType();
eventReceiver.EventType = EventReceiverType.ItemFileMoved;
if (!DoesEventReceiverDefintionExistBasedOnCreationInfo(eventReceiver, list))
{
list.EventReceivers.Add(eventReceiver);
}
context.ExecuteQuery();
}

[/csharp]

Unapplying event receivers is pretty easy to, but remember you are modifying the collection so you have to ensure that the enumeration can execute! That is why you see the two LINQ chains.

[csharp]

public static void UnApplyEventReceiver(ClientContext context, List list)
{
EventReceiverDefinitionCollection eventReceiverDefinitionCollection = list.EventReceivers;
context.Load(eventReceiverDefinitionCollection);
context.ExecuteQuery();
List ids = eventReceiverDefinitionCollection.Select(eventReceiverDefinition => eventReceiverDefinition.ReceiverId).ToList();
foreach (EventReceiverDefinition definition in ids.Select(eventReceiverDefinitionCollection.GetById))
{
definition.DeleteObject();
context.ExecuteQuery();
}
}

[/csharp]

Share