Thursday, January 8, 2015

A No-Code Way to Hack SharePoint's URLs to Filter by Managed Metadata and Show Child Terms

    Managed Metadata is a beautiful thing. Creating a query string that filters by a managed metadata field and shows child terms is not a beautiful thing. Thankfully I just found an efficient way to build a query string to filter by managed metadata while showing child terms and not requiring code of any kind.

    If you're not familiar with the pain points of filtering by managed metadata, Rightpointer John Wefler captured these pain points way back in 2011. Short blog short: you can't filter by managed metadata and show parent terms using a typical list view.

    Or can you?

    The answer is yes you can filter by managed metadata and show child terms. MSDN may want you to think that you need to build these manually by writing out GUIDs and syntax by hand, but the quickest way to achieve this is to use the metadata navigation feature to help build query strings.

    You may be thinking that this means you're going to have the deal with an ugly beast that is the managed metadata navigation filter which resides on the left-hand side of every page in your site. I know, no me gusta, but it's only temporary.

    Here's how to filter by managed metadata while showing child terms and avoid permanently displaying the managed metadata navigation.

    1. Create a view in your library.
    2. Turn on metadata navigation in the library via Library Settings. If it's not available, you need to enable the site feature.
    3. In your view, filter by your managed metadata term using the managed metadata navigation.
    4. Copy the URL after .aspx. This is your filter. It should look something like this:
      ?FilterField1=ABC_Category&FilterValue1=33&FilterLookupId1=1&FilterOp1=In&
      TreeField=ABC_Category&TreeValue=8c7e340c-b1b4-4f33-9a88-ab9cc4f27b77 &
      OverrideScope=RecursiveAll&ProcessQStringToCAML=1&RootFolder=
      %2Fnews%2FPages

    5. Create a new page.
    6. Add the app part for the library.
    7. Configure the app part to use the view created in step 1.
    8. Publish the page.
    9. After the page is published, post-pend the URL with the filter from step 4 and hit enter. The page will reload and apply the filter.

      Note
      : I have seen this work differently in two environments. Sometimes after you hit enter, SharePoint will change the URL I enter and rearrange the syntax of the filter. It'll probably be best to compare URLs and see what works. It may resolve to be something like the URL below:
      ?RootFolder=%2Fnews%2FPages&TreeField=ABC%5FCategory&TreeValue=
      62d0a846%2D6eb0%2D4a82%2D820e%2D3b1b1ca52bcc#ServerFilter=
      FilterField1%3DABC%255FCategory-FilterValue1%3D31%252C44-
      FilterLookupId1%3D1-FilterOp1%3DIn-TreeField%3DABC%255FCategory-TreeValue
      %3D62d0a846%252D6eb0%252D4a82%252D820e%252D3b1b1ca52bcc-OverrideScope%
      3DRecursiveAll-ProcessQStringToCAML%3D1


      If SharePoint changes the syntax on you, use the changed syntax. This step may require trial and error on your part.
    10. Once the URL filter has been tested, save the URL to the appropriate place (i.e. Notepad, your Site Navigation, a quick links web part), so users accessing this page are directed to the correct query string.
    11. Once you've tested the that you can pass in your query string and show child terms in a managed metadata term set, return to step 3 and repeat as necessary.
    12. When done, turn off metadata navigation in your library.

    There's two things I like about this approach. First, it doesn't require code. A lot of solutions out there involve compiled code which isn't necessary. I don't mind creating CAML queries, but if I can do it all through the UI and not be a CAML jockey, the only thing I'm thinking is "Where can I sign up?" The second thing I enjoy is that this solution doesn't require building a nasty URL string by hand and/or worrying about fat-fingering GUIDs. An added bonus is that if your fields have consistent GUIDs across environments, you're in for a smooth ride. This means you can copy the URL query strings from one environment to another easily. If you have different GUIDs, you'll need to start from the beginning of this post in each environment.