Contents tagged with SharePoint

  • Build JS file for .net Constants class

    Tags: PowerShell, javascript, SharePoint, SharePoint 2013

    It’s pretty common practice for me to have a Constants class in all my projects, especially so in SharePoint projects where you are likely to have Field name, Content Type ID’s and probably some GUID’s that you need.

    As I find myself more and more developing javascript solutions, I want access to those constants on the client side.  So taking inspiration from SharePoint (which generates a Strings object in javascript – see /_layouts/15/<lcid>/string.js, this file is auto generated by stsadm.exe.  I decided to cobble together a little script to build my js file.

    Say you have a .net constants class similar to this (I also use nested classes in my constants class).

    // Note: This file is autogenerated in JS for use on the client side.
    //       Do NOT put any sensitive string values in it.
    public static class MyStrings
    {
        public static class NestedOne
        {
            public static class NestedTwo
            {
                public const string Foo = "FooString";
                public const string Bar = "BarString";
    
                public static class NestedThree
                {
                    public const string Address1 = "AddressLine1";
                }
            }
    
            public static class NestedTwoTwo
            {
                public const string Location = "Location";
            }
    
            public const string AnotherOne = "SomeValue123";
        }
    }

     

    And use this PowerShell scripts (it’s a litle muddly I know, but it does work nicely!)
    Note: You could remove the string builder, its just there to help with debugging.

    The script is going to recursively loop through all your nested classes and build the required javascript file.

    clear
    $dllPath = 'C:\Constants.dll' #Path to dll containing Constants class
    $constantsClassName = "MyStrings" #Name of the .net constants class
    $jsClassName = "MyJsStrings"; #Name of the object in Javascript
    $outputJsFilePath = "C:\dump\MyJsStrings.js" #Place to save output js file
    
    # StringBuilder is just for debugging, you can change to simply write to stream
    $sb = New-Object -TypeName "System.Text.StringBuilder"
    $stream = [System.IO.StreamWriter] $outputJsFilePath
    
    function Append([string] $val) {
    	[Void]$sb.AppendLine($val)
    }
    
    Append "/* Copyright message ... "
    Append " * This file has been auto generated, do NOT edit"
    Append " */"
    
    function WriteFields ([System.Reflection.MemberInfo]$member, $parent) {
    	foreach($f in $member.GetFields() | where { $_.FieldType.Name -eq "String"}) {
    		$t = $jsClassName+"."
    		
    		if(-not [System.String]::IsNullOrWhiteSpace($parent)) {
    			$t += $parent+"."
    		} 
    		$t += $member.Name+"."+$f.Name+"='"+$f[0].GetValue($null)+"';"
    		Append $t
    	}
    	Append ""
    }
    
    function Recurse ([System.Reflection.MemberInfo]$member, $parent) {
    	WriteFields $member $parent
    	
    	foreach($mem in $member.GetMembers() | where { $_.IsClass -eq $true }) {
    		if(-not [System.String]::IsNullOrWhiteSpace($parent)) {
    			Append ($jsClassName+"."+$parent+"."+$member.Name+"."+$mem.Name+"=function(){};")
    			Recurse $mem ($parent+"."+$member.Name)
    		} else {		
    			Append ($jsClassName+"."+$member.Name+"."+$mem.Name+"=function(){};")
    			Recurse $mem $member.Name
    		}
    	}
    }
    
    # Load the dll
    # Doing it this way doesn't lock the file, could also be done with a new AppDomain
    
    $fileBytes = [IO.File]::ReadAllBytes($dllPath)
    
    $assembly = [Reflection.Assembly]::Load($fileBytes)
    
    # Get Constants class, could easily be modified if you have more that one class
    $classes = $assembly.GetTypes() | where { $_.Name -eq $constantsClassName }
    
    Append ("var "+$jsClassName+"=new Object();")
    
    foreach($c in $classes) {
    	foreach($m in $c.GetMembers() | where { $_.IsClass -eq $true }) {
    		$t = $jsClassName+"."+$m.Name+"=function(){};"
    		Append $t $m.Name
    		Recurse $m
    	}
    }
    
    Write $sb.ToString()
    $stream.Write($sb.ToString())
    $stream.Close();
    $stream.Dispose();

     

    The output is something like this…

    /* Copyright message ... 
     * This file has been auto generated, do NOT edit
     */
    var MyJsStrings=new Object();
    MyJsStrings.NestedOne=function(){};
    MyJsStrings.NestedOne.AnotherOne='SomeValue123';
    
    MyJsStrings.NestedOne.NestedTwo=function(){};
    MyJsStrings.NestedOne.NestedTwo.Foo='FooString';
    MyJsStrings.NestedOne.NestedTwo.Bar='BarString';
    
    MyJsStrings.NestedOne.NestedTwo.NestedThree=function(){};
    MyJsStrings.NestedOne.NestedTwo.NestedThree.Address1='AddressLine1';
    
    MyJsStrings.NestedOne.NestedTwoTwo=function(){};
    MyJsStrings.NestedOne.NestedTwoTwo.Location='Location';
    

     

    Add a link to that file in VS or add it to your _reference.js file and you’ll get nice intellisense!!

    Hope you find this as useful as I did!

    more...

  • Newly deployed SharePoint site definitions not found in PowerShell

    Tags: SharePoint 2013, PowerShell, SharePoint

    This is a new problem for me, something that I have done many times in SharePoint 2010.  I deploy a new site definition to SharePoint (in this case from Visual Studio 2012, although I can’t see it will matters), pop into PowerShell (in my case I use PowerGUI) and try to create a site from the new definition.

    However, when in PowerShell, running a script similar to this

    $web = Get-SPWeb $SiteURL
    $templates = $web.GetAvailableWebTemplates(1033)
    $templates | Foreach {
    	Write-Host $_.Name
    }

    You find that your new site definition is not listed in with all the other templates.

    Go and look in SharePoint, create a site and bingo, it’s there.  Weird.

    The problem is around caching in PowerShell sessions.

    Restarting IIS and SQL service didn’t work, so I had a quick Google and found this post.

    What a pain…so I quickly (with the help of this article) created a PowerShell cmdlet.

    Note: Make sure when you run the x64 version of InstallUtil (with from the VS x64 command line or C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe) otherwise you wont find it when you run

    Get-PSSnapin –registered

     

    Confused

    I’m not entirely sure why I have never come up against this before having done it multiple times, perhaps its an update to PowerGUI and the way it handles sessions or perhaps it’s a change in SharePoint 2013 caching.  I don’t know!

     

    Code for the PlugIn

    Copied from the link above!.  Don’t forget to add a reference to System.Management.Automation (C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll) and Microsoft.SharePoint

    [Cmdlet(VerbsCommon.Reset, "SPContext")]
    public class RecycleSPContext : PSCmdlet
    {
            
        [DllImport("kernel32.dll")]
        private static extern IntPtr FreeLibrary(IntPtr library);
    
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
    
        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string lpFileName);
            
    
        protected override void ProcessRecord()
        {
            Type sprequestmanager = typeof(SPFarm).Assembly.GetType("Microsoft.SharePoint.SPRequestManager", true, true);
            Type spthreadcontext = sprequestmanager.Assembly.GetType("Microsoft.SharePoint.Utilities.SPThreadContext");
            MethodInfo setcontext = spthreadcontext.GetMethod("Set", BindingFlags.Static | BindingFlags.NonPublic);
            Type[] genericArguments = new Type[] { sprequestmanager };
            MethodInfo setcontextgeneric = setcontext.MakeGenericMethod(genericArguments);
            // set the current sprequest manager to null!
            setcontextgeneric.Invoke(null, new object[] { null });
    
            IntPtr p = GetModuleHandle("OWSSVR.DLL");
            FreeLibrary(p);
            string stsadmPath = SPUtility.GetVersionedGenericSetupPath("ISAPI", 15);
            p = LoadLibrary(stsadmPath + @"\OWSSVR.DLL");
                
            WriteObject("SharePoint context restarted at " + DateTime.Now.ToString());
        }
    
    }

     

    And the Installer

    [RunInstaller(true)]
    public class RecycleSPContextInstaller : PSSnapIn
    {
        public override string Description
        {
            get { return "Recycle the SP Context"; }
        }
        public override string Name
        {
            get { return "RecycleSPContext"; }
        }
        public override string Vendor
        {
            get { return "Vendor Name"; }
        }
    }

    more...

  • Moved to the Cayman Islands.

    Tags: Cayman, SharePoint, Personal

    Those of you that know me in the physical world will know that I got a job in the Cayman Islands and have been whittering on about it for that last couple months!

    Although very excited and looking forward to, what my (Spanish) fiancé would call a “real summer”, I can’t argue, the UK has painfully unpredictable weather!  I’m gutted that I’m not going to be in the UK for the Olympics – totally gutted – I almost said no to the job based purely on that!

    I’ll be working as a SharePoint Dev for a company called DMS Organization (note the z not s!!) – its going to take some getting used too, spelling everything incorrectly!!

    Hopefully its going to be interesting challenge.

    I was planning to widen the scope of this blog, to not only .net, SharePoint etc geeky code stuff, but some stuff about the Cayman Islands and the surrounded countries.  Travelling is certainly high on our agenda and we plan on seeing as much as possible, using our weekends to the max!

    I have never been to the Cayman Islands before and I have never lived outside of the UK before, its all new and at times its difficult to focus the mind and remember that I have to start a new job, be smart and perform for what looks like a pretty dynamic organisation.  I’ve had several “first days” and don’t generally get nervous anymore – I know what I can and cant do.  I’m most intrigued to see how its done in another country and the Cayman seems interesting…a UK overseas territory, having our bank holidays and some cultural aspects etc, but with what seems heavy influence from the US.

    That of course is what I have inferred from speaking to a few different people who live there or have lived there – I must say, I’ve spoken to immigration a couple of times and not overly impressed, “blood from a stone springs” to mind!  I’ve also been warned about “Caribbean Time” !!

    Immigration is a problem, I have been granted a visa, but my fiancé cannot be a dependant on my visa, only when married can she be a dependant.  This is not resolved yet and while of course Luki is going to come out, exactly on what terms has yet to be decided!  Personally I think this is very old fashioned and they need to step it up – marriage is not as big-a-part of the world as it once was, we have been living together for several years – if this can be proved, like in many countries, she should be allowed.

    Cayman is (apparently) famous for a its scuba diving, boasting such a place as “Stingray City”, I’ve never done scuba diving before, only snorkelling a few times, I certainly plan on doing a PADI course and seeing some of the underwater world.  Again those that know me will know I love my bike (bicycle) and will be purchasing one on the island to get involved in what looks like an excellent little community.  And I can’t wait to go running along the beach with a quick swim to cool me down every km!

    That’s something I’ll have to get used too…Cayman uses the imperial system, crazy.  Ohh…and you don’t pay income tax…a nice bonus!

    Well, that’s enough about the “plans”, time for a dodgy airline meal, a quick siesta and get on with doing some of them!

    A couple pics from my journey!

    IMG_0713

    Train to London – progress.

    IMG_0716

    Boarding!

    IMG_0718

    My view!

    more...

  • Display content from Reusable HTML list in a MasterPage

    Tags: SharePoint

    This is as useful as it is simple!

    Having a footer for example in your master page without the overhead of being responsible for its maintenance.

    Here is a simple WebControl that you can reference in your master page and supply a key.

    Control

    Note: You might want to handle the exception better!!

    public class DisplayReusableContent : WebControl
    {
        public string ContentTitle { get; set; }
    
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            try
            {
                SPList rcl = SPContext.Current.Site.RootWeb.Lists["Reusable Content"];
                SPQuery q = new SPQuery
                {
                    Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + ContentTitle + "</Value></Eq></Where>"
                };
                var items = rcl.GetItems(q);
                if (items != null && items.Count > 0)
                {
                    // Should only be 1!
                    writer.Write(items[0]["ReusableHtml"].ToString());
                }
            }
            catch (Exception ex)
            {
                writer.Write(ex.Message);
            }
        }
    }
    

     

    Register Control

    <%@ Register TagPrefix="my" Namespace="$Your-Namespace" Assembly="$Assembl" %>
    

    Use the Control

    <my:DisplayReusableContent ContentTitle="Copyright" runat="server" id="ruc1" />
    

    And that’s it – not life changing, but one for the tool-bag!

     

    more...

  • Unit testing for SharePoint 2010 development

    Tags: SharePoint, Testing

    When developing for SharePoint 2010 Unit testing is often overlooked and it shouldn’t be.  It’s true that SharePoint is a product and we don’t need to test that, but the code we write to extend is the same as all other code and needs testing.

    Being able to test it though does require a little thought (and potentially a change) to way to you structure your code.  Getting away from running operations against SharePoint inside “CreateChildControls” for example.  You could unit test this method, but personally I think of a web part like a view (or an asp.net code behind file), it’s for presentation logic, not manipulating data or running CAML queries.

    The purists amongst you will probably say that this is Integration tests and not Unit tests, and I guess you are correct, I should probably interface out the SharePoint OM etc etc … you are right, but for SharePoint dev, I think this is the best way forward taking time and effort into account – “Is the juice worth the squeeze?” – for me….NO!

    I know we don’t need to test the SharePoint OM, but we do need to test our CAML queries – that needs to be ran against a SharePoint implementation, and probably one provisioned with the required lists etc.

    Unfortunately getting going with Unit testing in Visual Studio 2010 for SharePoint is not as easy as it should be.  The problems are: SharePoint 2010 is .net 3.5 and 64bit. 

    • MSTest in Visual Studio cannot run tests in 64bit mode.
    • Visual Studio unit test framework is .net 4 only.
    • My favourite (and I think the best free) testing framework MBUnit doesn’t seem to play well with 64 bit in .net 3.5.  The behaviour I see is changing the project type to .net 3.5 simply prompts VS to upgrade the project.  I’ve not looked into this a great deal, but would certainly rather it worked!

     

    The solution that seems to be most popular is NUnit.  I only use NUnit for this, that’s a choice thing – its just looks dated to me!  I like Icarus test runner for MBUnit – a lot!

    NUnit doesn’t have great integration with Visual Studio, the few bits I found in the Extension gallery were again, .net 4 only.

    I recommend you download TestDriven.net – I’ve blogged about this before – I’m a fan!  It makes is super easy to debug and run tests in VS.  Add an External Tool link in VS specifically for NUnit – more on that in a bit.

    Creating your tests

    Once you’ve installed NUnit from here, and TestDriven.net you’re ready to go..

    In Visual Studio, create a class library project and add a reference to NUnit.framework (and probably Microsoft.SharePoint).

    Make sure the project is targeting the .net 3.5 framework and the platform target is x64.

    Consider you have this simple little helper method just to get you the URL of an item

    public class Class1 : IDisposable
    {
        SPWeb _web;
    
        /// <summary>
        /// Inject SPWeb
        /// </summary>
        public Class1(SPWeb web)
        {
            _web = web;
        }
    
        /// <summary>
        /// Simple example of running a CAML query
        /// </summary>
        public int GetItemIDByTitle(string itemTitle)
        {
            if (String.IsNullOrEmpty(itemTitle))
                throw new ArgumentNullException("itemTitle", "cannot be null or empty");
    
            try
            {
                SPList configList = _web.Lists["Some List"];
                SPQuery query = new SPQuery();
                query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + itemTitle + "</Value></Eq></Where>";
    
                //Should only be 1!
                SPListItemCollection items = configList.GetItems(query);
                if (items.Count > 0)
                {
                    return items[0].ID;
                }
            }
            catch (Exception)
            {
                throw;
            }
            return 0;
        }
    
        /// <summary>
        /// Cleanup
        /// </summary>
        public void Dispose()
        {
            if (_web != null)
            {
                _web.Dispose();
            }
        }
    }
    

     

    You can see I am injecting an SPWeb into the class through the constructor.  The method is running a little bit of CAML.

    Not the most useful of code snippet I agree!!

    Write this little test…

    public class DummyTests
    {
        Class1 _provider;
        SPSite _site;
    
        [TestFixtureSetUp]
        public void Setup()
        {
            _site = new SPSite("http://sp2010");
            _provider = new Class1(_site.RootWeb);
        }
    
        [TestFixtureTearDown]
        public void TearDown()
        {
            _site.Dispose();
            _provider.Dispose();
        }
    
        [Test]
        public void Get_Item_URL_By_Title_Test()
        {
            string itemTitle = "Some Title";
            int expectedId = 1;
    
            var item = _provider.GetItemIDByTitle(itemTitle);
    
            Assert.AreEqual(expectedId, item);
        }
    }
    

     

    As mentioned before you have a couple of options for running the tests (there are more, you could buy ReFactor which has some nice stuff – but I haven’t got and can’t afford that!)  I recommend you do both, TestDriven is great for quickly running and debugging a test and the NUnit test runner is great to see all the green ticks when running all your tests!  Even if it is an old, ugly interface with more “80’s grey” than anyone should have to deal with!

    Once you have TestDriven.net installed, you can simple right click on the test to debug it…

    image

    For NUnit, create add a new External Tool entry in VS.  Tools –> External Tools…

    image

    In the command – be sure to target the 64bit version, actually its just nuit.exe, so I should say be sure NOT to target the x86 version!!

    In the arguments text box, use the helper to get the placeholders for BinDir and TargetName, adding the “/run” argument will run the tests automatically when the nuit runner opens.

    You’ll then get a new entry on the Tools menu – hit that and your tests should run….

    image

    Lovely!

    More / Resources:

    more...

  • Call a PowerShell script from SharePoint feature reciever

    Tags: SharePoint, PowerShell

     

    This is not likely to be something you use on a day to day basis, and I can see how some people might disagree with this method – preferring to use other techniques e.g. SharePoint project types etc in VS.

    I just see this as another way to skin the same cat!  A very handy tool to have in your box.

    I have used this for different things, but provisioning lists and adding some content to those lists a common thing.  It’s much easier to use PowerShell to do certain things, deploying a solution every time is just a pain and not overly good use of time waiting for VS to do its thing and recycle app pools left right and centre – so I work with PowerShell on my dev box.

    This then comes in when deploying to stage or production (yes, at this point you could create the artefacts perfectly in your VS solution, but time is money people…spending hours working and essentially still be at the same point I am now, just doesn’t interest me in the slightest – I have no interest in writing code just for the sake of writing code, it much achieve something).

    However, if my project/solution were to be sold for mass reuse on farms that were totally out of my control – I would not use this method.

    You need to add a reference to System.Management.Automation

    I created a simple class called PowerShellProxy that has a couple of helper methods, but this being the important one!

    public static void RunFromFile(string filePath, bool addSharePointSnapIn)
    {
        #region Arg Validation
    
        if (String.IsNullOrEmpty(filePath))
        {
            throw new ArgumentNullException("filePath", "Cannot be null or empty");
        }
        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException("File not found", filePath);
        }
    
        #endregion
    
        try
        {
            PowerShell ps = PowerShell.Create();
            if (addSharePointSnapIn)
            {
                ps.AddScript("Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction Continue");
            }
    
            string script = ReadFileContent(filePath);
            ps.AddScript(script);
            var result = ps.Invoke();
    
    

     

    You can then just pass in the file path of your ps1 file and you’re away.  Personally I have created a folder within the Layouts folder in my VS solution – that way it’s nice and neat and easy for source control.

     

    More:

    more...