Quick - TSQL select XPath from XML Data Type with namespace

 

Examples on MSDN shows the full TSQL syntax for XPath query in a TSQL statement, this has been supported since SQL Server 2008.

SELECT CatalogDescription.query(' declare namespace PD="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription"; <Product ProductModelID="{ /PD:ProductDescription[1]/@ProductModelID }" /> ') as Result FROM Production.ProductModel

This returns:

<Product ProductModelID="19"/>
<Product ProductModelID="23"/>

Wildcard in XPath Query

This is a much easier syntax with Wildcards that isn't well know.

SELECT CatalogDescription.query('/*:ProductDescription[1]/@ProductModelID') as Result
FROM Production.ProductModel

This returns:

19
23

Plenty of people will tell you using Wildcard matches in XPath is the worst thing in the world.  But I think if you just want to do a quick query, this is fine.

So, this is what can happen if you hack SP javascript files

 

SharePoint 2010's April 2014 CU introduced a bug with copy and paste. 

Bform.debug.js 381,869 11-Feb-2014 12:37
Bform.js 249,012 30-Jan-2014 16:39
Form.debug.js 211,134 11-Feb-2014 12:37
Form.js 126,783 30-Jan-2014 16:39

 

This was fixed and released in SharePoint 2010's August 2014 CU.
http://support.microsoft.com/kb/2760757

Bform.debug.js 381,888 15-Jul-2014 11:17
Bform.js 249,022 15-Jul-2014 11:17
Form.debug.js 211,153 15-Jul-2014 11:17
Form.js 126,793 15-Jul-2014 11:17

 

Story

On December 10, 2014, before we patched to the August 2014 CU level.  A certain very naughty person (me) couldn't wait and decided to offer a quick hack to the Javascript for the users over the holidays.  He even did a bak backup file of the original Form.js

 

image

 

We have now applied the August patch, but unfortunately, you can see:

bform.js, bform.debug.js, form.debug.js all updated.

Form.js is NOT updated.

Copy and paste still doesn't work in our environment.

 

Oops.

 

While a cheating way would be that we install the patch on another environment, and copy the correct Form.js file over. 

We'll be experimenting in this dev environment to see what is the best way to revert and go back to the supported path.  Stay tuned for a follow up article.

TypeScript Definition file for SPServices v0.1

 

Here's something I have wanted to write for a long time, both as Thank-You to Marc Anderson's work on SPServices, as well as for personal learning of the TypeScript language.

 

Adding TypeScript Definition reference:

image

 

$().sp (intellisense)

image

 

$().SPServices.defaults.cacheXML

image

 

$().SPServices.Version()

image

 

$().SPServices.SPCascadeDropdowns({ ... })

image

 

And one more.

$().SPServices({ ... })

image

 

Syntax Error Detection that TypeScript does so well. 

Except for the error message.

Repeat after me in a ROBOT way.  "String is missing apply from type Function".

What it means is I was expecting a function why did I find a string. 

And because Javascript can be surprisingly retarded, TypeScript tries to accommodate and wonders: perhaps this string is a function in disguise - so let me look for the apply method on this object.  NOPE.  It is not a function.   /s

 

image

 

 

Bonus.  TypeScript understands SPServices returns a JQueryXHR promise object.

image

 

Wait.  Where's all the other methods?

 

This is v0.1...

 

Download

https://static1.squarespace.com/static/5527bff2e4b0b430660b0d10/5527c30de4b030eeeef09715/5527c30ee4b030eeeef09d1c/1418221412217/jquery.SPServices.d.ts

Also, how do I get this into Marc's repo?

And I say to ASHX for SharePoint: make me a folder.

Sometimes, I do get to do some on-premises farm stuff.  Because deep in my soul, I'm a hardcore dev.  Muahaha.

Scenario

In InfoPath, we want to be able to:

  • Send people to a folder within a document library, for them to upload attachments. 
  • Each form has its own unique ID, say "1234".  The folder will be <site>/Attachments/1234/
  • The folder doesn't need to be created when it's not used.  That is, it would be great to create the folder ON DEMAND
  • Finally, InfoPath is quite dumb.  It only has a hyperlink.

 

Solution

  • Create a HTTP Handler that takes this URL:  <site/sitecollection>/_layouts/InfoPathHelper/InfoPathHandler.ashx?folder=<site>/attachments/<ID>
  • Create a folder on demand, and then respond via a HTTP Redirect.

 

Steps

 

image

  1. Add a ashx handler to your SharePoint solution.  CKSDev has great template for this.
  2. Add code to ProcessRequest
    public void ProcessRequest(HttpContext context)
    {
        if (!string.IsNullOrEmpty(context.Request.QueryString["folder"]))
        {
            CreateFolderAndRedirectResponse(context);
            return;
        }
    }

  3. Add a function to check for the folder, create it if we need it, and end with a redirect.

    private void CreateFolderAndRedirectResponse(HttpContext context)
    {
        // <site-collection>/_layouts/InfoPathHelper/InfoPathHandler.ashx?folder=<site>/

        var path = context.Request.QueryString["folder"];
        var server = new Uri(SPContext.Current.Web.Url);
        var url = string.Format("{0}://{1}{2}", server.Scheme, server.Authority, path);

        // elevate permission to create the folder.
        SPSecurity.RunWithElevatedPrivileges(() =>
        {
            try
            {
                using (var site = new SPSite(url))
                {
                    using (var web = site.OpenWeb())
                    {
                        SPFolder folder = web.GetFolder(path);
                        SPFolder f = folder;
                        List<SPFolder> folders = new List<SPFolder>();
                        SPDocumentLibrary library = folder.DocumentLibrary;
                        if (library == null)
                        {
                            return;
                        }
                        while(f.Url.ToLower() != library.RootFolder.Url.ToLower()){
                            if (f.Exists || string.IsNullOrEmpty(f.Url))
                            {
                                break;
                            }

                            folders.Add(f);

                            f = f.ParentFolder;
                            if (f == null)
                            {
                                // if this happens we're in trouble
                                return;
                            }
                        }


                        if (folders.Count > 0)
                        {
                            // we are in a GET request - need to allow unsafe updates
                            web.AllowUnsafeUpdates = true;
                            folders.Reverse();
                            foreach (SPFolder f1 in folders)
                            {
                                if (!f1.Exists)
                                {
                                    f1.ParentFolder.SubFolders.Add(f1.Name);
                                }
                            }
                            web.AllowUnsafeUpdates = false;
                        }
                    }
                }
            }
            catch (Exception ex)
            {

            }
        });

        context.Response.Redirect(path, true);
    }

  4. Wait what's all the strange looking nested folder stuff?  That's right, as a bonus, if you specify nested folder within the document library, the HTTP Handler will create those too!

    folder=/attachments/1234/1235/
  5. InfoPath is super simple, just add a Hyperlink to the URL

    image

    Link to Data Source:

    concat("/_layouts/InfoPathHelper/InfoPathHandler.ashx?attachments?folder=", my:ID)

 

See it running

 

image

Copying SP2013 Workflow XAML files between VSNET projects

The Error

If you copy Workflow or Workflow Custom Activity objects between your SharePoint VSNET projects, sometimes you would see these errors:

Project file must include the .NET Framework assembly 'WindowsBase, PresentationCore' in the reference list.

Project file must include the .NET Framework assembly 'WindowsBase' in the reference list.

 

Why

This is actually a result of VSNET getting quite confused.  It thinks your workflow.xaml files are WPF XAML files.

image

 

The Build Action "Page" is special and tells VSNET that this is a WPF Page object.  Which then triggers the compiler requirement that the necessary libraries are not included in the project.

This can happen when you copy Workflow or Workflow Custom Activity files from one project to another, then use VSNET to "Include in Project"

image

 

The Fix

Is to tell VSNET the correct Build Action for an Workflow XAML file:

image

 

The correct Build Action for Workflow XAML objects is XamlAppDef

Go through your project and check every XAML file.

 

Result

image

 

Happy again.