Contents tagged with SharePoint 2013

  • SharePoint App “Fast People Search”

    Tags: SharePoint 2013, Apps, Perspicuity

    The requirement came up for us as a company to get a little app into the App Store.

    As a consultancy we generally work on projects for specific clients, as such there isn’t a great deal of scope to work on apps for general release.

    As we needed to get something up there we rooted around some POC projects that we’ve worked on in the past and selected the one closest to completion.

    This is a SharePoint hosted app, making use of the SharePoint REST API.  Using jQuery and Knockout.js for some MVVM binding.

    This app is targeted at being used as an App Part.  Giving the ability to perform a quick people search without leaving the current page.

    Whilst you can configure the fields to search inside the app part properties, as well as the max number of results to return.  If you want full blown search, you’re best of going to the search centre.  But that is not the use case for this app.

    Take a look at the app here, it’s free of course!

    more...

  • SharePoint: Incoming mail in a development environment

    Tags: SharePoint 2013, Mail

    If you’re cutting any code for SharePoint, you’ve probably got yourself a nice standalone VM with everything isolated and working just about so.

    So, what happens when that rare project comes in where you need to work with incoming mail and need to test/mock it?

    There are plenty of articles out there for testing outgoing mail and most point to smtp4dev.

    Incoming mail is however a little more complex, or so it seems.  In our development environment we probably don’t want to think about exchange and all the baggage that comes with it.  We want it all isolated.

    Follow through the below technet article to set up the SMTP service and incoming mail on SharePoint, its not worth going through it all again here.

    Extra steps I did in this was to:

    1. Create an alias in IIS6 SMTP domains, just a vanity thing! 
    2. Update the hosts file to make sure this new alias points to 127.0.0.1
    3. Make sure I use my new alias when setting up incoming mail in SharePoint CA.


    http://technet.microsoft.com/en-us/library/cc262947(v=office.15).aspx

    Now, we have the SMTP setup on our local machine, but we don’t want to mess around with Exchange or DNS etc, so we’re going to simply force outlook to use the local box as the SMTP server.

    Open up outlook, create a new account, setup manually and select POP.

    In the SMTP Outgoing mail settings simply put in the alias name.

    The import one is to uncheck “Automatically test account settings when Next is clicked”.

    It really doesn’t matter about the username or password (unless you have for some reason setup auth in your SMTP settings).

    You will keep getting a prompt saying that Outlook can’t connect to the incoming mail server, if you really care about this, you can simply add a real life pop account for the incoming (obviously it’ll start downloading all the mail in that account!).

    Something like this and you’re good to go…

    (sp2013.com is the alias I setup for my dev server)

    image

    Hope this helps.

    more...

  • Resize SharePoint 2013 App Part

    Tags: SharePoint 2013, javascript, Apps

    The new App Model of SharePoint 2013 comes with several options for development, one of these being an app part, which from the users perspective works very much like the web parts of old!

    However, from a developers point of view these work differently.  They are basically iframes pointing to your App Part page, which through the elements.xml file you can configure to point to any page.  By default Visual Studio will prompt you to create a separate aspx page as you create your Client WebPart aka App Part.

    As you’ll know iframes need a fixed width and height, this is less than ideal and that’s an understatement of epic proportions!!

    But wait, there is a solution!  From what I can see though it is dependant on you setting the app part page to the Default.aspx page of your App.  What you need is the senderId parameter from the query string and from what I can see you only get this with the Default.aspx page.

    Using the below carefully created xml and post message to the parent with the sender id you can resize the iframe based on the content.

    This needs to of course be called after the UI of your app part has been loaded, this could be in the well know jQuery function.

    $(document).ready(function () {
        resize();
    });

    or in the callback of your async data loading method.

    I use a little function to help me get query string params…

    getQueryStringParameter: function (name) {
         var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
         return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
    }

    And here is the little beauty to resize your iframe.

    var w = "100%"; // or some other dynamic way to get the width
    var h = $(document).height(); // or the height of your wrapper in the app part
    window.parent.postMessage("<message senderId=" + utils.getQueryStringParameter("SenderId") + ">resize(" + w + "," + h + ")</message>", "*");
     

    I don’t think for one second this is ideal, but it does work and from what I can see is the recommend way.

    In my opinion this is a step backwards in the development process and I’m very keen to see how I can do this with my own Client App Part page.

    Hope this helps.

    more...

  • Visual Studio cleared / deleted my ascx.g.cs file when adding a Register declaration in my web part

    Tags: SharePoint 2013, Visual Studio 2012, WebParts

    Having landed on this page, you’ve most likely experienced the joy of VS clearing the contents of your ascx.g.cs file when adding a Register declaration, in the hope you can simply drop in your super whizzy snap bang custom control.

    Well, firstly rest assured you have not killed anything.  VS will rebuild the file for you.

    In the background VS communicates with SharePoint when you save the ascx file to build that cs file and if there are any issues, it just bums out and builds nothing.  Awesome!

    You will probably find that you need to deploy your assembly containing the namespace before you try and use it in your web part.  That way when VS talks to SharePoint, it knows about your namespace.

    More info, some comments from MS and lots of user experience/anger can be found here.

    http://connect.microsoft.com/VisualStudio/feedback/details/776340/visual-web-part-in-vs2012-code-in-ascx-g-cs-is-erased#tabs

    more...

  • 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...

  • 1