Friday, 3 May 2013

SharePoint 2013 - Delegate Controls - Beware of throwbacks to the SharePoint 2010 14 Hive

Delegate controls are particularly useful in SharePoint when you want to add functionality to all pages within your site without changing the master page. For example, if you want to add an external JavaScript library (such as JQuery) to every page, you can do this easily by registering a delegate control. An example of this approach can be seen here: http://blogs.msdn.com/b/kaevans/archive/2011/04/06/adding-jquery-to-every-page-in-sharepoint-with-delegate-controls.aspx

A delegate control is registered through an Elements.xml with a ControlSrc property pointing to your custom delegate control.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Control Id="AdditionalPageHead"
           Sequence="100"
           ControlSrc="~/_controltemplates/MyAppName.Core/MyDelegateControl.ascx" />
</Elements>
Problem is, the above code will work in SharePoint 2010 but NOT in SharePoint 2013. You will get an exception like the following:
DelegateControl: Exception thrown while building custom control 'Microsoft.SharePoint.SPControlElement': System.Web.HttpException (0x80004005): The file '/_controltemplates/MyAppName.Core/MyDelegateControl.ascx' does not exist.    
 at System.Web.UI.Util.CheckVirtualFileExists(VirtualPath virtualPath)    
 at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)    
 at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)    
 at System.Web.Compilation.BuildManager.GetVPathBuildResult(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean ensureIsUpToDate)    
 at System.Web.UI.TemplateControl.LoadControl(VirtualPath virtualPath)    
 at Microsoft.SharePoint.Utilities.SPUtility.CreateUserControlFromVirtualPath(TemplateControl tctlPage, String sControlPath)    
 at Microsoft.SharePoint.SPControlElement.BuildCustomControl(TemplateControl tctlPage, String sControlAssembly, String sControlClass, String sControlSrc, XmlNode xnElementDefinition, SPFeatureDefinition featdefElement, String sElementId)    
 at Microsoft.SharePoint.WebControls.DelegateControl.BuildCustomControlResilient(SPControlElement ctlelemDefinition)

The control itself DOES exist - so this is a somewhat misleading exception. Looking at this issue more closely, SysInternals ProcessMon will show you the way:



Looking closely, it is actually referencing the 14 Hive rather than the 15 Hive as a throwback to SharePoint 2010. So to fix this, you simply need to update your ControlSrc to include 15 in the path:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Control Id="AdditionalPageHead"
           Sequence="100"
           ControlSrc="~/_controltemplates/15/MyAppName.Core/MyDelegateControl.ascx" />
</Elements>
As an alternative, you could also use a Module and a custom action for registering a ScriptLink to something like jQuery or knockout.js.

DDK

Monday, 25 March 2013

SharePoint 2013 - Fix for Exception - Microsoft.SharePoint.SPException: Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))

I received the following exception when creating new custom field types in SharePoint 2013. I couldn't even open the List Settings page (via the Web UI, SharePoint Designer or SharePoint Manager).

To resolve, you simply have to rename any potentially problematic custom field types e.g. rename fldtypes_MyCustomField.xml to zzfldtypes_MyCustomField.xml". You can find your field types located in %Program Files%Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\XML. Restart IIS after each rename.

This will get you back up and running - and you will now know what custom SharePoint field type is causing the issue.

Full Exception Details as below:

Getting Error Message for Exception System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> Microsoft.SharePoint.SPException: Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)) ---> System.Runtime.InteropServices.COMException: Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))   
at Microsoft.SharePoint.Library.SPRequestInternalClass.GetFieldTypeInfo(String bstrUrl, Boolean bInternal, Object& pvarTypeNames, Object& pvarTypeDisplayNames, Object& pvarTypeShortDescriptions, Object& pvarBaseRenderingTypeNames, Object& pvarFieldTypeClasses, Object& pvarFieldEditorUserControls, Object& pvarPropertySchema, Object& pvarTypeInfoFlags)   
at Microsoft.SharePoint.Library.SPRequest.GetFieldTypeInfo(String bstrUrl, Boolean bInternal, Object& pvarTypeNames, Object& pvarTypeDisplayNames, Object& pvarTypeShortDescriptions, Object& pvarBaseRenderingTypeNames, Object& pvarFieldTypeClasses, Object& pvarFieldEditorUserControls, Object& pvarPropertySchema, Object& pvarTypeInfoFlags) -
-- End of inner exception stack trace ---   
at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)   
at Microsoft.SharePoint.Library.SPRequest.GetFieldTypeInfo(String bstrUrl, Boolean bInternal, Object& pvarTypeNames, Object& pvarTypeDisplayNames, Object& pvarTypeShortDescriptions, Object& pvarBaseRenderingTypeNames, Object& pvarFieldTypeClasses, Object& pvarFieldEditorUserControls, Object& pvarPropertySchema, Object& pvarTypeInfoFlags)   
at Microsoft.SharePoint.SPFieldTypeDefinitionCollection..ctor(SPWeb web, Boolean internalCall)   
at Microsoft.SharePoint.SPField.GetFieldTypeDefinitionForType(SPFieldCollection fields, String strType)   
at Microsoft.SharePoint.SPField.get_FieldTypeDefinition()   
at Microsoft.SharePoint.SPField.get_TypeDisplayName()   
at ASP._layouts_15_listedit_aspx.__Render__control13(HtmlTextWriter __w, Control parameterContainer)   
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)   
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)   
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)   
at Microsoft.SharePoint.WebControls.AjaxDelta.RenderChildren(HtmlTextWriter output)   
at System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer)   
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)   
at Microsoft.SharePoint.WebControls.AjaxDelta.Render(HtmlTextWriter writer)   
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)   
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)   
at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer)   
at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)   
at Microsoft.SharePoint.WebControls.SharePointForm.Render(HtmlTextWriter output)   
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)   
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)   
at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)   
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)   
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)   
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)   
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)   
at Microsoft.SharePoint.WebControls.UnsecuredLayoutsPageBase.RenderChildren(HtmlTextWriter writer)   
at System.Web.UI.Page.Render(HtmlTextWriter writer)   
at Microsoft.SharePoint.WebControls.DeltaPage.RenderToBase(HtmlTextWriter writer)   
at Microsoft.SharePoint.WebControls.DeltaPage.Render(HtmlTextWriter writer)   
at Microsoft.SharePoint.WebControls.UnsecuredLayoutsPageBase.Render(HtmlTextWriter writer)   
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)   
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)   
at System.Web.UI.Page.HandleError(Exception e)   
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)   
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)   
at System.Web.UI.Page.ProcessRequest()   
at System.Web.UI.Page.ProcessRequest(HttpContext context)   
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()   
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

DDK

Saturday, 23 March 2013

Microsoft Licensing - Can I Purchase Microsoft Software from overseas and use it here in Australia?

With the Federal Government inquiry into the inflated prices of software in Australia, it has become quite clear (officially) that there is a price differential between Australia and most of the world (especially the US). When the CEOs (such as Pip Marlow from Microsoft) were asked why the prices are different, it basically comes down to the fact "because we can". When I did commerce at UNSW, this was known in palatable terms as "extracting the consumer surplus through price discrimination".

The enormity of the price difference became clear when we decided to purchase Microsoft Visual Studio 2012 with MSDN here in Oz.

As per http://msdn.microsoft.com/en-au/subscriptions/buy.aspx

Australia - $21,202 (AUD)
USA - $13,299 (USD)



It has been suggested by some (including Choice Magazine no less) that it would be much cheaper to send someone over to the USA in luxury, purchase it and then bring it back home (if that were neccessary).

However, this would then not be in compliance with the licensing agreement as outlined at http://www.microsoft.com/licensing/licensing-options/open-regional.aspx. The line that specifically prohibits you purchasing from another region (such as the USA) is "Customers and resellers must place agreements and orders with partners within the same defined region."
 
So if you even attempt to purchase from a buyer outside your region and ship it back in, you would be outside the terms of the agreement and have unlicensed and illegal software. This got me thinking laterally within the bounds of our licensing region. Looking at other options within the APAC (Asia Pacific) region, the prices are as follows:
Country of Purchase Amount (Local Currency) Amount in AUD
Korea ₩15,730,600.00 $13,461.00
Brunei
$17,814.00
$13,653.00
Singapore $17,814.00 $13,653.00
Malaysia RM46,081.00 $14,196.00
Thailand ฿451,605.00 $14,763.00
Phillipines Php643,970.00 $15,113.00
New Zealand $26,369.00 $21,040.00
New Caledonia $13,299.00 $12,754.00
Australia
$21,202.00
$21,202.00
Indonesia
$15,294.00
NA - Rupiah Not Provided
Vietnam $15,294.00 NA - VND not provided

So you can save $7,741 by purchasing the same product from New Caledonia as opposed to Australia.

Looking into the License terms and conditions for MSDN with Visual Studio Ultimate specifically, there is a list of "General Terms and Conditions" that can be found here:
http://www.microsoftvolumelicensing.com/ProductPage.aspx?pid=422. More specific product use rights can be found here: http://www.microsoftvolumelicensing.com/userights/Downloader.aspx?DocumentId=6131

Conclusion:
1) There is nothing specifically in the January 2013 Microsoft Product Usage Rights document about purchasing a product from another country (inside or outside your licensing region) and using it elsewhere.
2) There is only a subtle hint on the "Microsoft Open Programs Affiliate Participation Policy" page that you shouldn't be contacting partners outside the APAC licensing region (say an Australian going to the US) to purchase your software.

To be completely in the clear, you can purchase from somewhere like New Caledonia (or Korea) and save yourself in excess of $8K. This is provided it's OK that:
1) You have someone at the other end who can receive your invoice for you (or you will fly/kayak/swim over there to receive it) - or you don't care about the invoice at all.
2) You don't need the DVDs.

For $8K, many would consider these to be small sacrifices indeed!

[Update 18/07/2013] - I've had a few emails about this post. We ended up purchasing the AU licenses as it was seen as too much of a risk on a large purchase to have a potentially unsupported product. Microsoft also called us up to confirm we were who we said we were - so if you desperately want to save money and still have a legitimate MSDN license, I recommend you set up both postal and phone redirection!

DDK



Friday, 18 January 2013

How do I fix Visual Studio 2012 so that it is usable? (aka how to Change the VS 2012 UI Skin)

After using Visual Studio 2012 for a couple of months, I became extremely frustrated with:
  1. Not being able to easily differentiate between icons based on their colors
  2. That all the Visual Studio 2012 menus are all in CAPITAL LETTERS (with their inherent lack of readability in this form). Personally, I prefer to reserve capitals for strictly for acronyms.
  3. The black and white color theme in Visual Studio 2012. It's not the best thing to wake up to in the morning!
To fix this I recommend you do what I did and:

1) Install NiceVS - which will give you back the color icons you know and love from VS 2010 (so you can easily tell your object browser from your Code Definition Window) . It also removes the unnecessary capitalization of the text in the main drop down menu. Install it from here:
http://visualstudiogallery.msdn.microsoft.com/a36021f0-770a-4258-854e-724e9d12b8a6

2) Install the Visual Studio 2012 Color Theme Editor from here:
http://visualstudiogallery.msdn.microsoft.com/366ad100-0003-4c9a-81a8-337d4e7ace05

Small changes like these can make a big difference to the usability of VS 2012 on a daily basis. I'd have to say that it would have been better if both these pieces of functionality were already built in to the RTM of Visual Studio 2012. A big thank you to the authors for their respective extensions.








DDK

I can't see the GAC in Windows Explorer by browsing to %WINDOWS%\ASSEMBLY anymore. What is wrong?

As per http://msdn.microsoft.com/en-us/library/9x295t9k.aspx
"In earlier versions of the .NET Framework, the Shfusion.dll Windows shell extension enabled you to view the global assembly cache in File Explorer. Beginning with the .NET Framework 4, Shfusion.dll is obsolete. "

Consequently, something that has worked since version 1.0 of the .NET framework is now [cough] "broken" - no more going to C:\WINDOWS\ASSEMBLY anymore! Now you will just get the ugly view of the GAC internals.

There are 3rd party utilities to help you browse the GAC (e.g. .NET Reflector can help in this regard) - but it is simple enough to just pipe or redirect the output of gacutil.exe to a text file to read in your favorite text editor:

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC>gacutil -l > c:\temp\gacu
til.txt


DDK


Thursday, 18 October 2012

Hiking in New Zealand (Milford Track) - The best way to get and consume Free Offline Topographic Maps for use on Android Phones

I'm about to go hiking on the Milford Track in New Zealand (one of the "Great Walks") which has the debatable title of being the "finest track in the world". I booked the huts throught the New Zealand department of conservation (DOC - http://www.doc.govt.nz/) - with much of the season well into 2013 already sold out. I was lucky to nab some of the last cabin places.

Looking at the map images online and Google Maps itself, it got me thinking that "fine" as the track  may be, I was still keen on having a GPS will full topographic maps along for the ride. I wasn't so keen on forking out for a dedicated GPS device, so I naturally looked to my Samsung SII Android phone as a solution.

Even though Google Maps added full offline capabilities in July 2012, there are many limitations to both the maps and the offline implementation which led me to search for much better solutions for a hiking GPS system. Google Maps offline is basically more of an "alpha" product which:
  1. Only Allows 6 offline mapping regions (not sure how they arrived at 6); each of which is limited to ~90MB.
  2. Doesn't currently allow layers (like topo or satellite images)
  3. Doesn't provide any kind of offline searching capability even within those offline maps (this requires a full data connection).
The Google Maps solution was a workable (though not slick) solution for guiding us on the drive to Te Anau Downs (where the boat to the Milford Track picks up walkers). However, Google Maps just has the track at its most basic level - not have enough detail to help with indicating how far we are away from the next cabin.

I found a good solution was to do the following for full offline maps for the Milford Track:
  1. Download and Install to the Mobile Atlas Creator (MOBAC) on your PC (Windows/Linux/OSX). You may also need to download and install the Java Runtime Environment (JRE) 1.6 or above). Download from http://mobac.sourceforge.net/. Even if you have a GEOTIFF available (e.g. the freely available GeoTiffs from the NZ Topographic Authority), you cannot just upload it to your phone as the images are typically massive and would take an aeon to load and render.
  2. Use the Default World Map via in MOBAC source to scroll to view New Zealand (if you just use the NZ Topo Maps you will just see a large group of arrows with no way to navigate to New Zealand).
  3. Switch to the NZ Topo Maps Datasource in MOBAC (see http://mobac.sourceforge.net/quickstart/using3_1.htm for details). You should now see the full New Zealand topographic map.
  4. Zoom into the Area you want and mark it as a selection. As per http://mobac.sourceforge.net/quickstart/using3_3.htm
  5. Click the settings button change the Output folder to the location you want.
  6. Click Create Atlas and select your desired output mapping format (I use Alpine Quest lite which is available for free on Google Play) and all the neccessary images for your selection (at required zoom levels) will be downloaded and aggregated into the requested file format.
You now have an exported map consumable by your offline GPS application.
To consume your newly created atlas in Alpine Quest:
  1. Copy the output file (e.g. Apline Quest Map (.AQM file) to the Alpine Quest /maps directory on your Phone's SD card
  2. In AlpineQuest, click on Maps and Click Open Offline Map.
  3. You can now view your map and add waypoints as needed on your fully detailed topographical map!
GPS functions on phones are also notoriously power-hungry. Just in case, I've also purchased a couple of spare batteries and a solar charger as backup.

Auf Wiedersehen!
DDK

Monday, 8 October 2012

WCF 4.5 - Host Unreachabl​e when calling a WCF service from soapUI

The WCF Test Client (WCFTestClient.exe) is Visual Studio's disappointingly basic tool for testing your WCF services. If you have your hopes up that the the Visual Studio 2012 WCF Client tool for .NET 4.5 is any better, forget about it. It is still so simple that it doesn't support client X509 Certificates or even username and passwords. Other tools like Fiddler and Wireshark are also compulsory items on the toolbelt (along with .NET coded integration unit tests). Fiddler supports client certificates out of the box and works a charm (especially for REST services).
I have used soapUI (http://www.soapui.org/) extensively for the past few years for basic integration testing of WCF (with basic endpoint bindings) and SAP web services. I've been using those also to test out connections to my current client's back-end banking systems.

soapUI isn't perfect though - as there are differences in interpretations of the WS-* standards between the Java and the .NET worlds - and soapUI is based on a Java stack. One such problem that you'll find with calling Microsoft WCF services with wsHttpBinding soapUI is that you get the following exception when you use the default settings:



    
      http://www.w3.org/2005/08/addressing/soap/fault
   
    
      
         
            s:Sender
            
               a:DestinationUnreachable
             
         
         
            The message with To '' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher.  Check that the sender and receiver's EndpointAddresses agree.
          
      
   

This is because there is no "To" entry in the header of the message. The fix for this is to go to the soapUI WS-A tab and ensure that the "add default wsa-To address is checked on" as per the screenshot below:

Friday, 7 September 2012

Neutral Bay Public School - Spring Carnival - Mini Golf 2012 a big success!



Some photos of the Neutral Bay Mini-Golf course that we constructed to raise funds for Neutral Bay Public School. It was such a hit that we even had queues of eager golfers going around the corner!

Thanks again to all those who helped with drills, equipment, blood, sweat and tears. It was a real adventure designing, planning, constructing and dismantling the course.






















 


Till Next Time,
DDK