Creating geospatial mashups with Visual Fusion

Marek Koenig specializes in Business Intelligence, SharePoint and Custom Development.

Marek Koenig specializes in Business Intelligence, SharePoint and Custom Development.

Tell me if this sounds familiar: You’re asked by your boss to find the correlation between the data coming out of your data warehouse and some Excel spreadsheets. He wants to know why some of the call centers have been getting inundated recently with higher call volumes. Just looking at these two sources of data you’re having trouble finding a good answer to the question. You realize that the data includes addresses of your call centers and the areas that they support.

To achieve better insight and understanding, you can load up your data into Visual Fusion, a data visualization platform built by IDV Solutions. The data can then be consolidated into a single interactive view. No more having to go through different reports, trying to match it up with sales data, and seeing if socio-economic factors are related. Read more of this post

Upcoming webinar: maximize video in the enterprise

David Lozzi

David Lozzi

Microsoft SharePoint is a powerful solution that can manage content across organizations in a variety of ways. Recently, I had the opportunity, as part of a Slalom Consulting team, to work with RAMP and help create its enterprise product MediaCloud for SharePoint. We integrated RAMP’s impressive media solutions with SharePoint to provide a rich video experience inside SharePoint itself.

MediaCloud for Sharepoint enables team members to upload a video directly into SharePoint, which then handles processing, querying, etc., using RAMP’s secure cloud-based storage and delivery. Once the video is ready, the user is notified and video playback is accessible through RAMP’s custom player. The video is searchable through SharePoint, including spoken words—meaning users can stay in SharePoint from start to finish. As a result, organizations can get the most from their video content through the SharePoint solution they already have in place. Read more of this post

Migrating Audience Targeted Information

Slalom Consultant Maarten Sundman

Slalom Consultant Maarten Sundman specializes in .NET, SharePoint, and Silverlight solutions and has experience in the Financial Services, Software, and Utilities and Energy sectors.

Sometimes you’ll encounter a scenario where you need to move a site from one environment to another and the site is using Audiences. Now I’m personally a bit of a fan of Audiences for simple out of the box targeting of information. However, it has one pretty major flaw. Audiences are fundamentally environment specific. There is no out of the box method for remapping or moving audience targeted information and have it still work properly on the other side. This is due to a number of reasons which I’m not going to go in to in this blog post. However, here is a tool that can help with this.

This tool is pretty straight forward with only two command, import and export:

  • Export—Generates a file with a mapping of audiences to be used when updating the new environment.
  • Import—Based on your mapping file updates the content in the new environment to use the new environments audiences.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Server;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Navigation;
using Microsoft.Office.Server.WebControls.FieldTypes;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.Office.Server.Audience;
using System.IO;

namespace WithinSharePoint.MigrateAudiences
{
class Program
{
internal static List Audiences = null;
internal static Dictionary<string, Audience> RemappedAudiences = null;
static void Main(string[] args)
{
try
{
if (args.Count() == 2)
{
SPSite site = new SPSite(args[1]);
foreach (Audience a in GetAudiences(site))
{
Console.WriteLine(a.AudienceName + “,”+ a.AudienceID.ToString());
}
}
if (args.Count() == 3)
{
SPSite site = new SPSite(args[1]);
SPWeb RootWeb = site.OpenWeb();
Audiences = GetAudiences(site);
RemappedAudiences = AudienceMap(args[2]);
ScanWeb(RootWeb);
}
else if ((args.Count() < 2) | (args.Count() > 3))
{
WriteUsage();
}
}
catch(Exception ex)
{
Console.WriteLine(“ERROR:” + ex.Message);
WriteUsage();
}
}

internal static void WriteUsage()
{
Console.WriteLine(“Usage: WithinSharePoint.MigrateAudiences -EXPORT [URL TO RETRIEVE AUDIENCES] >> AudienceExport.csv”);
Console.WriteLine(“Usage: WithinSharePoint.MigrateAudiences -IMPORT [URL TO SCAN AND UPDATE] [FILEPATH]“);
Console.WriteLine(“File is a text document with this format (Audience ID is the ID of the audience in the SOURCE environment, not the destination):”);
Console.WriteLine(“AudienceName,AudienceID”);
}

internal static void ScanWeb(SPWeb web)
{
web.AllowUnsafeUpdates = true;
ScanLists(web.Lists);
try
{
ScanNavigation(web.Navigation.GlobalNodes);
ScanNavigation(web.Navigation.QuickLaunch);
}
catch (Exception ex)
{
Console.WriteLine(“Error updating navigation. ” + ex.Message);
Console.WriteLine(web.Url);
}
foreach (SPWeb child in web.Webs)
{
ScanWeb(child);
}
web.AllowUnsafeUpdates = false;
}

internal static void ScanLists(SPListCollection Lists)
{
foreach (SPList list in Lists)
{
if (list.Fields.ContainsField(“Target_x0020_Audiences”))
{
ScanItems(list.Items, “Target_x0020_Audiences”);
}
else if (list.Fields.ContainsField(“Audience”))
{
ScanItems(list.Items, “Audience”);
}
}
}

///

/// Scans and updates all audience targetted sharepoint navigation nodes with audiences from the new environment
///

///internal static void ScanNavigation(SPNavigationNodeCollection Nodes)
{
string value = “”;
string[] values;
bool pendingupdate = false;
Char[] splitter = new Char[] { ‘;’ };
SPNavigationNode node;
for (int i = 0; i < Nodes.Count; i++ )
{
node = Nodes[i];
string newvalue = “”;
if (node.Properties.Contains(“Audience”))
{
value = node.Properties["Audience"].ToString();
value = value.Replace(‘,’, ‘;’);
values = value.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
foreach (string val in values)
{
if (RemappedAudiences.ContainsKey(val))
{
//update with new audiences
pendingupdate = true;
newvalue += RemappedAudiences[val].AudienceID + “,”;
}
else
{
//this is to preserve existing unknown audiences
newvalue += val + “,”;
}
}
if (pendingupdate)
{
node.Properties["Audience"] = newvalue;
node.Update();
}
}
}
}

///

/// Scans all items in an audience targetted list and updates them with new environments audiences
///

//////internal static void ScanItems(SPListItemCollection items, string AudienceField)
{
Console.WriteLine(“Scanning and updating list ” + items.List.Title);
bool ListUpdate = false;
Char[] splitter = new Char[] { ‘;’ };
SPListItem item;
for(int i = 0; i < items.Count;i++)
{
try
{
item = items[i];
string value = “”;
if(item[AudienceField] != null)
{
if (!String.IsNullOrEmpty(item[AudienceField].ToString()))
{
bool PendingUpdate = false;
string NewValue = “”;
value = item[AudienceField].ToString();
if (value.Contains(“,”))
{
value = value.Replace(‘,’, ‘;’);
}
//Console.WriteLine(value);
string[] audiences = value.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
foreach (string a in audiences)
{
//Console.WriteLine(a);
if (RemappedAudiences.ContainsKey(a))
{
//add remapped audience to update
PendingUpdate = true;
NewValue += RemappedAudiences[a].AudienceID + “,”;
}
else
{
//keep unknown audiences in the item
NewValue += a + “,”;
}
}
if (PendingUpdate)
{
//don’t ask why sharepoint uses csv for audience id’s and then appends ;;; at the end
item[AudienceField] = NewValue + “;;;;”;
ListUpdate = true;
item.UpdateOverwriteVersion();
}
}
}
}
catch(Exception ex)
{
Console.WriteLine(“Error reading line item:” + ex.Message);
Console.WriteLine(items[1][AudienceField].ToString());
Console.WriteLine(ex.StackTrace);
}
}
if (ListUpdate)
{
items.List.Update();
}
}

///

/// Reads the contents of the audience export file to generate a mapping of equivalent audiences in the target environment
///

//////
/// String – AudienceID of Source Environment
/// Audience – Audience in New/Target Environment
///
internal static Dictionary<string, Audience> AudienceMap(string FilePath)
{
Dictionary<string, Audience> map = new Dictionary<string, Audience>();
StreamReader reader = new StreamReader(FilePath);
string input = null;
while ((input = reader.ReadLine()) != null)
{
string[] line = input.Split(‘,’);
if(line.Count() == 2)
{
var match = from a in Audiences where a.AudienceName == line[0] select a;
foreach (Audience m in match)
{
map.Add(line[1], m);
}
}
}
return map;
}

///

/// Returns a list of all audiences from the target site collection
///

//////
internal static List GetAudiences(SPSite site)
{
List audiences = new List();
SPServiceContext context = SPServiceContext.GetContext(site);
AudienceManager aMan = new AudienceManager(context);
foreach (Audience a in aMan.Audiences)
{
audiences.Add(a);
}
return audiences;
}
}
}

Importing Profiles in SharePoint

Slalom Consultant Maarten Sundman

Slalom Consultant Maarten Sundman specializes in .NET, SharePoint, and Silverlight solutions and has experience in the Financial Services, Software, and Utilities and Energy sectors.

A common need when testing SharePoint solutions is having test accounts setup a certain way so they can do something. Whether this is a test account for a country, language, etc. Normally it’s painful to set up these accounts as typically they end up being setup by hand in the user profile service application; therefore I’ve gone ahead and built a tool which  reads all the attributes for a profile from a CSV and updates the users profiles (code below). This also works for normal accounts if you’re trying to import in bulk via Excel or some other data source for a one time import which can happen during migrations from other systems.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
using System.Web;

namespace WithinSharePointUpdateUserProfile
{
class Program
{
static Char[] Splitter = new Char[] { ‘,’ };
static UserProfileManager uMan = null;
static Dictionary<UserProfile,Dictionary> UsersToUpdate = new Dictionary<UserProfile,Dictionary>();

static void Main(string[] args)
{
if (args.Count() == 1)
{
SPSite site = new SPSite(args[0]);
DisplayProfileAttributes(SPServiceContext.GetContext(site));
}
else if (args.Count() == 2)
{
try
{
SPSite site = new SPSite(args[0]);
uMan = UserManager(SPServiceContext.GetContext(site));
ReadFile(args[1]);
foreach (UserProfile K in UsersToUpdate.Keys)
{
UpdateUser(K, UsersToUpdate[K]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Help();
}
}
else
{
Help();
}
}

static void DisplayProfileAttributes(SPServiceContext Context)
{
UserProfileConfigManager config = new UserProfileConfigManager(Context);
ProfilePropertyManager pMan = config.ProfilePropertyManager;
CorePropertyManager cMan = pMan.GetCoreProperties();
foreach (CoreProperty prop in cMan.PropertiesWithSection)
{
Console.WriteLine(“Display Name : ” + prop.DisplayName + ” Internal Name : ” + prop.Name);
}
}

static void Help()
{
Console.WriteLine(“Usage is: WithinSharePointUpdateUserProfile http://WEBAPPURL C:\\Path\\To\\File”);
Console.WriteLine(“To display a list of profile fields: WithinSharePointUpdateUserProfile http://WEBAPPURL&#8221;);
Console.WriteLine(“File Format is:”);
Console.WriteLine(“USERNAME,CORP\\Username,FIELDNAME,FIELDVALUE”);
}

static UserProfileManager UserManager(SPServiceContext Context)
{
return new UserProfileManager(Context, true);
}

static void ReadFile(string Path)
{
StreamReader reader = new StreamReader(Path);
string input = null;
UserProfile UP;
Dictionary User;
while ((input = reader.ReadLine()) != null)
{
User = UpdatedAttributes(input, out UP);
UsersToUpdate.Add(UP, User);
}
}

static bool UpdateUser(UserProfile Profile, Dictionary ProfileChanges)
{
Console.WriteLine(“Updating user: ” + Profile.DisplayName);
try
{
foreach (string k in ProfileChanges.Keys)
{
if (Profile[k] != null)
{
Profile[k].Value = ProfileChanges[k];
Profile[k].Privacy = Privacy.Public;
}
}
Profile.Commit();
}
catch (Exception ex)
{
Console.WriteLine(“Error updating profile ” + Profile.DisplayName);
Console.WriteLine(ex.Message);
return false;
}
return true;
}

static UserProfile GetProfile(string Username)
{
return uMan.GetUserProfile(Username);
}

static Dictionary UpdatedAttributes(string row, out UserProfile Profile)
{
Dictionary result = new Dictionary();
string[] split = row.Split(Splitter);
Profile = GetProfile(split[1]);
for (int i = 2; i < split.Count(); i++)
{
result.Add(split[i], split[i + 1]);
i++;
}
return result;
}
}
}

SharePoint and Chrome

Slalom Consultant Maarten Sundman

Slalom Consultant Maarten Sundman specializes in .NET, SharePoint, and Silverlight solutions and has experience in the Financial Services, Software, and Utilities and Energy sectors.

A few months ago I posted an entry called SharePoint 2010 Scrolling detailing a method to get scrolling working on less supported browsers in SharePoint 2010. Along with some background on to why the method works.

I’ve had reason recently to revisit Chrome and SharePoint compatibility specifically as of late. In the process a different fix came out of it. One that is less heavy-handed. But more importantly I found out that the cause of the scrolling inconsistency on some browsers like iOS Safari and Chrome is not due to the causes that have been previously documented by other bloggers or myself. The cause is, in fact, a timing issue around execution of a specific bit of very important onload JavaScript.

The bit that doesn’t execute (and causes a systemic issue, one of the issues it causes is the scrolling weirdness), is: Read more of this post

Webinar: Accelerating SharePoint for Mobile Solutions on the AWS Cloud

Slalom Consultant Joel Forman

Slalom Consultant Joel Forman specializes in cloud computing and the Windows Azure Platform.

I wanted to take the opportunity to post about an exciting upcoming live webinar that is being co-delivered by Slalom Consulting and Amazon Web Services entitled Accelerating SharePoint for Mobile Solutions on the AWS Cloud.

On Wednesday, August 15th at 10:00 AM PST, we will bring several emerging topics together around mobility and the cloud. You will have the opportunity to learn more about how to make SharePoint applications available to your mobile users using the AWS cloud directly from an AWS Solution Architect. Then, we will demonstrate how they can quickly and securely mobilize SharePoint content with our SharePoint Mobile Accelerator. The Accelerator is a framework that can target both on-premise and cloud SharePoint implementations, and allows for rapid development of custom iPhone & iPad applications to enable your growing mobile workforce while maintaining corporate security standards.

Here are the individuals that will be presenting during this live session: Read more of this post

Creating a Drop Down Navigation Menu in SharePoint Using JavaScript

Slalom Consulting—Dennis Jackson

Dennis Jackson is a Slalom Consultant and Architect in our Dallas Portals & Collaboration Practice. He has over 15 years’ experience using databases and the web creating corporate intranets, call center applications, content management platforms, e-commerce, and self-service sites for Fortune 500 clients.

The Case
The built in navigation for SharePoint in general can take some getting used to. In 2010 it is much better, but there are some occasions where a client may want something that is different than the way that SharePoint wants to do it. In this case the client was asking for a drop down menu where a user could pick from “any of the team team sites” and “just go there”.

And if you were in a team site, then list the other ones.

But we have a preference in our practice for using out-of-the-box SharePoint first, and avoiding customizations if possible. So the approach that we ended up going with was client side JavaScript (JS) using the content editor web part to host the script.

The Plan
There are a few main parts of the JS that needed to be ironed out.

  • First, communicating with SharePoint to get a list of all the webs that were under this site.
  • Second, iterating over the results and appending them to a select drop down box with the needed data and labels.
  • Third, recognizing the dropdown changes and routing the user appropriately. Read more of this post

Accelerating SharePoint Mobile Development

Slalom Consulting—Jon Allegre

Jon Allegre is a Solution Architect for Slalom Consulting. Jon’s focus is on delivering solutions and strategies around mobility (iOS, Android, mobile HTML5), user experience, and alternative application hosting models (AWS, Azure).

Liberate Your Content

The amount of structured and unstructured content in the Enterprise is ever increasing and it is a challenge for organizations to manage and access this content. Numerous systems and tools are used by organizations to store, manage and surface corporate information to users. Microsoft SharePoint is a popular choice for a majority of the world’s largest businesses, enabling these activities for tens of millions of users.

A second phenomena occurring in today’s businesses is the mobilization of the workforce and the need to access this content from anywhere, from any device, whether connected to the Internet or offline. From the sales person or field worker to the executive on the go, there is considerable need for employees to have access to the most up to date content that pertains to their role in the organization.

Furthermore, to make the information useful, it must be delivered in a meaningful way to the end user. In some cases, this may mean a need in delivering the content to the end user in a rich, compelling experience versus simply allowing them to browse to the location of the content and viewing it. Read more of this post

Windows Server 8: Part 1—Active Directory

Slalom consultant and accomplished Microsoft systems developer Derek Martin sheds light on Windows Server 8 (WS8) through his insightful blog series focusing on his research within the technical preview documentation, personal experimentation with the product, and thoughts of how they can apply to the real world as soon as it is released to manufacturing (RTM).

One of the most stable and well designed pieces of software to come out of Microsoft–ever–is Active Directory. While its development was riddled with twists and turns (and the occasional run in with Novell), the identity platform for millions of businesses is a stalwart of stability. Few outside IT Administrators ever know of its existence–and that is the point. The basic ability to authenticate and gain access to corporate resources, be that a computer, a server or a file would not work without the consistent resiliency of this gorgeous database.

Slalom Consultant Derek Martin

Slalom Consultant Derek Martin is an accomplished Microsoft systems developer and integrator, experienced in developing and deploying SharePoint and CRM solutions, integrating line of business applications, and leveraging existing infrastructure investments.

The biggest advantages of Active Directory over other products is its ubiquity. Microsoft has spent untold sums making it accessible and secure to a variety of applications, the entire MSFT stack included. It also is the underpinning of major infrastructural components of many software packages including Exchange, Lync, SharePoint, and thousands of LoB applications. In recent versions, it has gained prominence in the realm of federation, enabling businesses to seamlessly federate their authentication and authorization stores using technologies like ADFS and Claims Authentication. The changes in WS8 around Active Directory continue to provide support for the major system components from previous versions (great backward compatibility) as well as the new features throughout Windows Server (describe later in this series) and support administrators by addressing common pain points. Here’s what’s new:

Simplified Deployment: Similar to Windows 8 Client where everything is touch first, in WS8 everything is PowerShell first! Deploying Active Directory is so much easier now that it can be accurately scripted.  All but the smallest companies have needs to deploy multitudes of AD servers.  In WS8, you can deploy Active Directory on multiple servers at once, export your graphical user interface  (GUI) based configuration to a series of PowerShell scripts and can clone brand new Domain Controllers (think sysprep on steroids) for rapid Active Directory forest topology builds.

Safer Virtualization Support: This exact issue has bitten me! What’s the cardinal sin with virtual machines and Active Directory? DON’T P2V a DC (without following very complex prescriptive processes). The dreaded rollback USN will bite you. Active Directory in WS8, however, recognizes that virtual domain controllers are what enterprises need, so they’ve built in additional replication logic to keep time synchronized with hosts and algorithms that keep things in check when they are virtualized.

These three updates with Active Directory, along with refined management experiences, new/simpler PowerShell commands will make administering your forest much easier. I’ll update this post as more information is learned about any of the underpinnings of Active Directory–I’m particularly interested to see if the schema has changed any!

Slalom Consulting’s Dallas office Slalom Consulting's Project & Cloud focus
Learn more about our Dallas office Learn more about Slalom Consulting Cloud

subscribe by emailSubscribe to follow new Cloud posts

Turning Quick Launch into a Tab control

Slalom Consultant Maarten Sundman

Slalom Consultant Maarten Sundman specializes in .NET, SharePoint, and Silverlight solutions and has experience in the Financial Services, Software, and Utilities and Energy sectors.

First, let me start this post by saying that I absolutely love that navigation in SP2010 is completely standard HTML. This is a ‘codeless’ method for turning that left navigation quick launch in to a nifty tab control. The use case for this was that for some landing pages people wanted tabs rather than quick launch but for everything else the normal quick launch. So how do you change the quick launch as needed to tabs? The answer is pretty simple.

Before we get into the details of how to build this, let’s take a step back and look at what the quick launch HTML looks like: Read more of this post

Follow

Get every new post delivered to your Inbox.

Join 126 other followers

%d bloggers like this: