Good Morning!, and what a wonderful Saturday morning it is, the scent of strawberries are in the air!
So I've been working on a public facing 365 website lately and making a few customisations, one request I received was to have the ability for users to add an item to a "mailing list" list, and they wanted maximum portability, so I thought, perfect for the JS-CSOM!
Such a simple idea, add an item to a list, just needs one field adding in very straight forward, or so I thought, so I created the js function and hooked it up, for auth users it worked like a charm but I ran into a problem when accessing it anonymously, I got the error "object doesn't support this method" when calling a new "SP.ClientContext", its a straight forward error meaning it cant find the function in any loaded libraries, so I thought right, gotta be SP not loading sp.js, simple, add a script link in there... no luck the same error came up, then I thought right, gotta be that the method is running before SP.js is properly loaded so I used "ExecuteOrDelayUntilScriptLoaded()" to encapsulate my code and make sure it runs after the code is loaded, published the js and checked it again... no luck!
So it has to be sp.js not loading correctly, remembering the SoD SharePoint is so fond of I then tried the trusty "SP.SOD.executeFunc('sp.js', 'SP.ClientContext', addToMailingList)", and it worked perfectly!
Code:
$("#ben-mailinglist-confirm").click(function () {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', addToMailingList)
});
function addToMailingList(metadata) {
var metadata = $("#ben-mailinglist-email").val();
if (metadata != "") {
var clientContext = new SP.ClientContext("/");
var list = clientContext.get_web().get_lists().getByTitle('MailingList');
var itemCreateInfo = new SP.ListItemCreationInformation();
var listItem = list.addItem(itemCreateInfo);
listItem.set_item('Title', metadata);
listItem.update();
clientContext.load(listItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, function () { $(".ben-mailinglist-success").show(); $(".ben-mailinglist-form").hide(); }),
Function.createDelegate(this, function () { $(".ben-mailinglist-failure").show(); })
);
}
else {
// validation
}
}
Saturday, 15 June 2013
Wednesday, 5 June 2013
SharePoint Online (Office365): Profile images broken / not coming up
Today I had a brilliant issue, I have a 365 authenticated site that uses profile images, these are surfaced in the "ContactFieldControl", I added profile pictures to the profiles and navigating to the mysites worked fine and the profile picture on the contactfieldcontrol worked too but then I opened it in a different browser and the profile image was broken in the webpart, that was strange I thought maybe an MS Job had deleted it so I went to the mysite and the image was there!, so I navigated back to the site and once again it shows up
So it appears if the image is loaded through the contact field webpart it shows as a broken image but if you navigate to the mysite or the image directly it worked
So how to fix it?
this issue appears to be in the first load of an image using the direct path to the image, i was hoping a cache clear or an update of the profiles would fix but but to my knowledge there is no OOTB way of fixing this so i resorted to using a dev's best friend, jQuery!
First I tried running a piece of jQuery on the page to preload the image using an ajax call but that didn't work
Then I noticed something interesting, whilst fiddling the page I saw that it also calls the following URL "/_layouts/15/userphoto.aspx?size=S&url=********", this URL links directly to the image, I thought this was interesting so I wrote a piece of jquery to take the source of the image and transform it into a URL like the one above and hey presto it worked!!
Code:
function checkProfileImages() {
$(".ben-imgborder img").attr("src", "/_layouts/15/userphoto.aspx?size=S&url=" + $(".ben-imgborder img").attr("src"))
}
So it appears if the image is loaded through the contact field webpart it shows as a broken image but if you navigate to the mysite or the image directly it worked
So how to fix it?
this issue appears to be in the first load of an image using the direct path to the image, i was hoping a cache clear or an update of the profiles would fix but but to my knowledge there is no OOTB way of fixing this so i resorted to using a dev's best friend, jQuery!
First I tried running a piece of jQuery on the page to preload the image using an ajax call but that didn't work
Then I noticed something interesting, whilst fiddling the page I saw that it also calls the following URL "/_layouts/15/userphoto.aspx?size=S&url=********", this URL links directly to the image, I thought this was interesting so I wrote a piece of jquery to take the source of the image and transform it into a URL like the one above and hey presto it worked!!
Code:
function checkProfileImages() {
$(".ben-imgborder img").attr("src", "/_layouts/15/userphoto.aspx?size=S&url=" + $(".ben-imgborder img").attr("src"))
}
Monday, 6 May 2013
Installing SharePoint Designer 2013 Issue: You must uninstall office pro plus first....
I came across this issue a while back while setting up a new development environment, i had installed VS2012, Office 2013 and was trying to install SPD 2013, I ran the setup and during the preflight checks it failed with the following message:
Why? why on earth must I un-install office to install SPD?, well as it turns out Office 2013 added a registry key(typical...) that the preflight checks, this key looks as though its not needed but is still added, possibly something that was meant to be deleted but wasn't.
So to fix it!:
Open regedit.exe (Run -> regedit -> Enter)
Find and delete the following key: HKEY_CLASSES_ROOT\Installer\Products\00005102110000000100000000F01FEC
Note: if you can't find the above key, just find the key with prefix: 00005102, and suffix: F01FEC, and delete it. (Before deleting it, backup this key by exporting it, never a good idea to mess with the registry before backing up the original state).
Now that that's gone, try the installer again, hopefully it should now let you install SPD unhindered!
Using the C# CSOM to interact with SharePoint Online
So, I had a requirement recently to allow a client to interact with their SPOnline site from their on-prem network, essentially being able to sync data from their on-prem LoB apps to their SPOnline site.
As any sp dev knows there is one main way of interacting with SharePoint remotely, that is through the supplied web services, this can be done either through interacting directly with the web services or by using the SharePoint client site object model which essentially just wraps a basic API around the web services, so its your preference on what you want to use.
Now with the CSOM any interactions with SharePoint are based around the context, to set up the context you need to pass in the credentials and authenticate the accessing user, in SP 2010 this was a feat to accomplish as there was no real way to pass in an authentication token to the context, with the release of SP2013 MS have made this significantly simpler, you can call in a class called "SharePointOnlineCredentials" this will handle any authentication you should need to do. this class is included in version 15 of the Microsoft.SharePoint.Client dll
Depending on how you have your dev environment set up you may encounter a "FileNotFoundException" pointing to "MSOIDCLIL.dll" this usually occurs if you have VS installed locally and have installed the dev tools but you haven't installed the client sdk, you can check this by navigating to this directory "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\Client", if that dir exists and has the dll then there is a broken link somewhere and you will need to reinstall the sdk, if it doesn't exist then a fresh install of the SharePoint Client SDK here.
By using this you now have open to you the full array of functions you can call with the CSOM that you can now call from your on prem network
Here is the code I have used to PoC the process, please use it as you see fit:
As any sp dev knows there is one main way of interacting with SharePoint remotely, that is through the supplied web services, this can be done either through interacting directly with the web services or by using the SharePoint client site object model which essentially just wraps a basic API around the web services, so its your preference on what you want to use.
Now with the CSOM any interactions with SharePoint are based around the context, to set up the context you need to pass in the credentials and authenticate the accessing user, in SP 2010 this was a feat to accomplish as there was no real way to pass in an authentication token to the context, with the release of SP2013 MS have made this significantly simpler, you can call in a class called "SharePointOnlineCredentials" this will handle any authentication you should need to do. this class is included in version 15 of the Microsoft.SharePoint.Client dll
Depending on how you have your dev environment set up you may encounter a "FileNotFoundException" pointing to "MSOIDCLIL.dll" this usually occurs if you have VS installed locally and have installed the dev tools but you haven't installed the client sdk, you can check this by navigating to this directory "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\Client", if that dir exists and has the dll then there is a broken link somewhere and you will need to reinstall the sdk, if it doesn't exist then a fresh install of the SharePoint Client SDK here.
By using this you now have open to you the full array of functions you can call with the CSOM that you can now call from your on prem network
Here is the code I have used to PoC the process, please use it as you see fit:
class Program
{
static void Main(string[] args)
{
args = new string[] { "CreateProjectList" };
if (args.Length != 1)
{
Console.WriteLine("Instanciate the program with a method
parameter:");
Console.WriteLine(" - GetLists");
Console.WriteLine(" - CreateProjectList");
}
else
{
switch (args[0])
{
case "GetLists":
Console.WriteLine("Getting lists from Online Site");
GetLists();
Console.WriteLine("List retrieval complete");
break;
case "CreateProjectList":
Console.WriteLine("Creating projects list in Online Site");
CreateProjectList();
Console.WriteLine("List creation complete");
break;
}
Console.ReadKey();
}
}
private class Configuration
{
public static string ServiceSiteUrl = "https://{mysite}.sharepoint.com";
public static string ServiceUserName = "{user}@{365-org}.onmicrosoft.com";
public static string ServicePassword = "{password}";
}
static ClientContext
GetContext()
{
var securePassword = new SecureString();
foreach (char c in Configuration.ServicePassword)
{
securePassword.AppendChar(c);
}
var onlineCredentials = new SharePointOnlineCredentials(Configuration.ServiceUserName,
securePassword);
var context = new ClientContext(Configuration.ServiceSiteUrl);
context.Credentials = onlineCredentials;
return context;
}
static void GetLists()
{
var context = GetContext();
var results =
context.LoadQuery(context.Web.Lists.Include(list => list.Title, list =>
list.Id));
context.ExecuteQuery();
results.ToList().ForEach(x =>
{
Console.WriteLine("List: " +
x.Title);
});
context.Dispose();
}
static void CreateProjectList()
{
ClientContext
clientContext = GetContext();
Web site = clientContext.Web;
// Create the project list.
ListCreationInformation
listCreationInfo = new ListCreationInformation();
listCreationInfo.Title = "Projects";
listCreationInfo.TemplateType = (int)ListTemplateType.GenericList;
List list =
site.Lists.Add(listCreationInfo);
// Add the category field to the list.
Field catField =
list.Fields.AddFieldAsXml(@"
<Field Type='Choice' DisplayName='Category' Format='Dropdown'>
<Default>IT</Default>
<CHOICES>
<CHOICE>IT</CHOICE>
<CHOICE>Sales</CHOICE>
<CHOICE>Research and Development</CHOICE>
<CHOICE>CSR</CHOICE>
</CHOICES>
</Field>
", true, AddFieldOptions.DefaultValue);
// Add list data.
ListItemCreationInformation
itemCreationInfo = new ListItemCreationInformation();
ListItem listItem =
list.AddItem(itemCreationInfo);
listItem["Title"] = "New public facing
website";
listItem["Category"] = "IT";
listItem.Update();
listItem
= list.AddItem(itemCreationInfo);
listItem["Title"] = "New Incident
Management System";
listItem["Category"] = "IT";
listItem.Update();
listItem
= list.AddItem(itemCreationInfo);
listItem["Title"] = "New internal sales
strategy";
listItem["Category"] = "Sales";
listItem.Update();
listItem
= list.AddItem(itemCreationInfo);
listItem["Title"] = "Youtube product
visibility";
listItem["Category"] = "CSR";
listItem.Update();
clientContext.ExecuteQuery();
}
Thursday, 11 April 2013
SharePoint Issue: Exception has been thrown by the target of an invocation while adding a CQWP
Summary Info:
SharePoint Version: 2010 Standard
OS:Windows 2008 R2
So, Yesterday I had another fantastically inexplicable issue.
I have this solution, this solution deploys a site definition, when the site is created, it activates a custom feature that processes the more complex requirements of the site, including some CQWP's whereby you been to set the listguid and weburl properties.
This solution was build and on both Dev and UAT it worked like a dream, but then it came to the production deployment, solution deployed, features activated, everything was looking rosey, until I tested creating a site, then boom "an unexpected error has occurred for correlation id.....", so there was me thinking there is an issue with the deployment that got glazed over, I checked the ULS logs for the correlation and there I found:
What! what the hell is that!, the content query web part couldn't be added, OK!, well that could be one of many issues:
So I checked the webpart in the gallery, it looked ok, I added a webpart to the page through the UI, configured it to look at the list and it worked! so the .webpart is fine, the namespace and features are fine, so it looks like the property setting.
I removed the code setting the properties and still the error occurred so as a process of deduction i took property after property out of the webpart until i found the properties breaking it, after taking the MainXsl, HeaderXsl and ItemXsl properties out of the .webpart file, the web parts deployed, why? good question!
So the SC I was deploying to was root and at "/" of the webapp so it cant be the URL of the properties.
Just to make sure I programatically set the urls of the xsl to the correct urls, when I did this I got another error!
Ok now we're getting further down the rabbit hole!
Then I started investigating the context properties programmatically and found that when deploying this the HttpContext was null. I know this has been known to mess up some context sensitive operations. so I added the following before I attempted to instantiate the webpart to add:
and viola! the web part started to deploy!
So in conclusion, the CQWP is very context sensitive, and to do anything programatically, make sure you have access to a HttpContext
SharePoint Version: 2010 Standard
OS:Windows 2008 R2
So, Yesterday I had another fantastically inexplicable issue.
I have this solution, this solution deploys a site definition, when the site is created, it activates a custom feature that processes the more complex requirements of the site, including some CQWP's whereby you been to set the listguid and weburl properties.
This solution was build and on both Dev and UAT it worked like a dream, but then it came to the production deployment, solution deployed, features activated, everything was looking rosey, until I tested creating a site, then boom "an unexpected error has occurred for correlation id.....", so there was me thinking there is an issue with the deployment that got glazed over, I checked the ULS logs for the correlation and there I found:
Error Message Exception has been thrown by the target of an invocation.
Error Stacktrace: at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at Microsoft.SharePoint.WebPartPages.SPPropertyInfoPropertyEntry.SetValue(Object control, Object value)
at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.ExtractLinks(Object property, Object value, Int32 propertyLocation)
at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.Serialize(PersonalizationScope scope)
at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.get_Links()
at Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartToStore(WebPart webPart, Int32 viewId, String viewGuid)
at Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartInternal(SPSupersetWebPart superset, Boolean throwIfLocked)
at Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPartInternal(WebPart webPart, String zoneId, Int32 zoneIndex, Boolean throwIfLocked)
at Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPart(WebPart webPart, String zoneId, Int32 zoneIndex)
at {Logic Namespace}.AddCQWebPart(SPWeb rootWeb, SPLimitedWebPartManager webPartManager, String webpartName, String zoneId, Int32 zoneIndex, Guid listId, String url)
What! what the hell is that!, the content query web part couldn't be added, OK!, well that could be one of many issues:
- SharePoint feature corruption
- CQWP I'm referencing isn't there
- Namespace is invalid
- Couldn't set the properties
So I checked the webpart in the gallery, it looked ok, I added a webpart to the page through the UI, configured it to look at the list and it worked! so the .webpart is fine, the namespace and features are fine, so it looks like the property setting.
I removed the code setting the properties and still the error occurred so as a process of deduction i took property after property out of the webpart until i found the properties breaking it, after taking the MainXsl, HeaderXsl and ItemXsl properties out of the .webpart file, the web parts deployed, why? good question!
So the SC I was deploying to was root and at "/" of the webapp so it cant be the URL of the properties.
Just to make sure I programatically set the urls of the xsl to the correct urls, when I did this I got another error!
Error Message Object reference not set to an instance of an object.
Error Stacktrace: at Microsoft.SharePoint.Publishing.WebControls.CmsDataFormWebPart.MakeSiteRelativeUrl(String xslServerRelativeUrl)
at Microsoft.SharePoint.Publishing.WebControls.CmsDataFormWebPart.SetXSLLink()
at {Logic Namespace}.AddCQWebPart(SPWeb rootWeb, SPLimitedWebPartManager webPartManager, String webpartName, String zoneId, Int32 zoneIndex, Guid listId, String Url, String& errorMessage)
at {Logic Namespace}
.AddCQPageWebPart(String pageUrl, String webPartName, String webPartZone, String listName)
Ok now we're getting further down the rabbit hole!
Then I started investigating the context properties programmatically and found that when deploying this the HttpContext was null. I know this has been known to mess up some context sensitive operations. so I added the following before I attempted to instantiate the webpart to add:
if (HttpContext.Current == null) { HttpRequest request = new HttpRequest("", rootWeb.Url, ""); HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter())); HttpContext.Current.Items["HttpHandlerSPWeb"] = rootWeb; }
and viola! the web part started to deploy!
So in conclusion, the CQWP is very context sensitive, and to do anything programatically, make sure you have access to a HttpContext
Saturday, 6 April 2013
Recipe: Cinnamon Cake!
Enter the humble cinnamon cake, this cake is a treat for anyone, even if you don't like cinnamon the flavors and textures of this simple wonder will bring you around!
Ingredients:
Ingredients:
- 300g of flour (use plain flour to get a thinner crunchier base or use self raising flour to make it a little thicker and spongier)
- 125g of Caster sugar
- 1/2 teaspoon of baking powder
- 125g of Butter
- 200ml whipping cream
- a couple of table spoons of cinnamon powder
- (Optional) thingly chopped apple or pear slices
Preparation
- Firstly Heat your oven to 200 degrees, a little under if its a fan jobbie
- Mix the flour, sugar and baking powder together in a cooking bowl
- Heat the butter in a pan until the butter is melted
- Add the butter to the flour mix and mix together well until all the butter is absorbed and the mix is in small crumbles
- pour the crumbles into a baking pan and flatten them out into a pie type crust, make sure there is an edge atleast a centimeter high depending on the size of the pan
- If you have fruit slices, add them now!
- Now you have 2 options!, either:
- Mix the ccinnamonwith the cream in a separate bowl, make sure the cinnamon is properly absorbed then pour the cinna-cream into your new crust
- the more fun way!, Pour the cream into your new crust then sprinkle the cinnamon ontop and with a spoon swirl the cinnamon around to absorb it, this makes funky cinnamon patterns
Heating
- Heat the cake for 10 minutes at 200 degrees then lower the temperature to 150 degrees for a further 15-20 minutes, until the pie crust is goldening
- Leave to cool before eating as the cream will need that time to set, when the cake has cooled the cake should be set, sometimes its a bit of an art!
Monday, 17 December 2012
Snowpenhagen - Denmark
copenhagen 2012
a few weeks ago we went to copenhagen, what a fascinating place!, it was covered in snow and full of crazy angled design!What started out as a weekend away turned into a 3 day marathon of exloring the town and the baked delights of copenhagen, now i know why the danish is so popular, ive heard denmark described as a "Culinary black hole" with the only thing to really make it outside of the country being the danish, i can understand why!, there is such a plethora of danishes, cream cakes and everything baked, as long as it has marzipan it seems to pass the danish cake standard and can be sold, dammmmn they are tasty!
denmark is a very very interesting mix between england and sweden, on the one hand it has the brilliant architecture, excellent public transport system, the people are friendly, the apartments are many and the balconies big, the environment is taken care of and the krowns are many which takes care of the swedish side, on the other side beer and alchohol is freely available anywhere, even burgerking, so many buildings are in a state of disrepair and chaos
its a very strange mix, but it seems to be working well for them
metro
the copenhagen metro is fantastic and tacky at the same time, they are all automated, so there is no drivers cabin, just some seats to sit at the front, they are a very strange mix, on the one hand it feels great to have technology wotk in an automated way, on the other hand it feels like a fantasy from the 1970's, this feels like something that was designed in the 70's, both on the outside and the inside
when you get inside and you can sit at the front you feel like your in black mesa touring through the facility, its brilliant!, for this reason alone i could take it every day
i do wonder how they work in rush hour, as people are inherently stupid when they need to get somewhere, they do random stupid things like try to jump on a train they know they cant, i wonder how good the sensors are on the doors or do those idiots get bruised by the closing doors on their faces, i hope they do, there is something to be said of a good dose of Darwinism
hotel
the hotel was the Bella Sky hotel in Bella Center, this was a brilliant hotel bit just because it shot out into the sky like a testament to Danish design but all around it was fantastic..... and it had its own wind turbine! :D
we got the joy of being on the 19th floor!, what a fantastic view but the fun part was the room numbers, it looks fun and is very stylish!
at night the hotel is a shining beacon to those who like colour!
from the 19th floor the view is just fantastic!, snow everywhere
i do have a tip though, if its really windy, go through the tunnel to get to the metro, its a wind tunnel and pushes you back, exactly what you need to wake you up and start your journey!
if your unsure of where to stay in copenhagen, definitely consider this one: http://www.bellaskycomwell.dk
emmerys
in the midst of exploring the town in the snow, and intense wind, and great sense of being lost we needed somewhere to take a coffee and leech some WiFi we passed some fancy pubs and some uninviting places, but in the midst of a random street near a random part we found the best coffee shop in Copenhagen , it was minimalist, clean, had a great simple brand and turned out to be a great bakery too!, with friendly staff what more could you want!
if you go to Copenhagen, you MUST go to emmerys
Link: http://www.emmerys.dk/
cakes
ahh one of the best bits, the cakation
the heart blueberry danish, nyam!
the tasty breakfast pastry "FRØSNAPPER", this pastry is simple, flakey pastry with a sweet taste and seeds on top, strange but tasty and not overly sweet
and ofcourse a danish!, covered in chocolate and marzipan, it was was a little too dry though!
saving the best till last, this little gem is the epitone of all danish cakery!, its called the kartoffelkage, or potato cake, its a light pastry with a vanilla cream covered in a slab of marzipan, its fantastic, light, airy and full of flavour!, nyamnyamnyam!!!
random
viking blood!, first time ive seen it bottled, bet its a tasty brew!
the skinny bitch, that was an utter bitch! one i dont want to see again, the taste and body was displeasing!
crazy cheese cutter, the plate raises so it always slices the right amount of cheese, it looks like a finger slicer!
green!!!
Subscribe to:
Posts (Atom)