VS.NET 2008, VSeWSS 1.3 and SafeControl

Oh VSeWSS how I've NOT missed you. 

I was compiling an old solution package for SharePoint 2007, this solution has 6 web parts but the WSP package's manifest only has SafeControl lines for 4 of them.  Somehow, it is discriminating against my newest 2 additions to the family.

In VS.NET 2010, the settings for whether a web part feature should be included in SafeControl is off the WSP Package view.  It automatically adds the current DLL, as well as giving us an option to add more additional assemblies (via the special package solution designer).

image

 

In VS.NET 2008 and SharePoint 2007, the way it determines whether or not to include a Web Part when it generates the manifest file seems...  almost, bizarre and magical.

 

This is how it works

  1. During packaging, VSeWSS reads the DLL to determine if there are web parts within it that needs a SafeControl line.
  2. When it finds them, it modifies a temporary file that it uses during packaging, under project\bin\Debug\solution\manifest.xml
  3. The packaging process than packs up everything under \solution\ into a WSP file, and the manifest file is stored within the WSP file.
  4. What's confusing, is that VSeWSS is not reading the right DLL that's compiled from this project, instead, if you have an older copy of the DLL in the GAC, it will actually read the GAC version over your newly built DLL.

    The end result, is that you think you are crazy and you don't understand why it's arbitrarily deciding to add 4 SafeControl lines, but not all 6.

 

Fix

The fix is pretty simple, if you manually deploy the DLL to the GAC first, then repackage again, it'll pick up the additional web parts within the DLL and add them to your SafeControl list.

 

Why have I never seen this before

If you are deploying to the local machine for testing, you actually may not even see this error - since when you deploy the currently built solution to the local machine it also puts the new DLL into the GAC. 

SharePoint Single Page Application day 4

Did a bit of clean up and finally I've got what I can call the first awesome screen shot.

This is a Single Page Application deployed to SharePoint, and talks to SharePoint via the Client Object Model as well as the REST interface.

The page does not Postback.  It always talk to SharePoint via AJAX.

 

So far:

  • Package 1 ASPX page in a solution package
  • Reference jQuery, Knockout
  • Layout using Twitter's Bootstrap
  • Grabs lists via Client Object Model
  • Grabs list items via REST interface
  • The darn thing is beautiful

 

To come next:

  • CRUD for list items
  • Document download
    • Document upload?
  • List paging
  • Use different icons for lists and document libraries on left navigation
  • A favicon
  • An actual Title for the page
  • Site navigation (this will do post back - since we'll be navigating between say http://server/ to http://server/publishing/ ).
  • Quick search / filter
  • An interesting picture thumb-nail viewer

 

Check it out on http://spaspa.codeplex.com/ and let me know what you think!

SharePoint 2010 as a Single Page Application (teaser)

What is a Single Page Application?  Essentially, an application disguised as a single web page.  Like the official "Twitter" web application.  You click, things happen, data is loaded and released asynchronously, layouts are arranged and displayed.  Like magic.

On a crazy Thursday afternoon I had the mad idea of building a Single Page Application on top of SharePoint.

This is a sneak preview of my work so far on this goal:

 

The story so far

  • Everything in a SharePoint farm solution
    • Deploys to /_layouts/JL-SPA/SPA.aspx - one single page!
  • UI layout using Twitter Bootstrap - what you see above is based on the Fluid example template
    • Twitter Bootstrap is based on Less.js
  • UI binding using Knockout.JS
  • Additional glue with jQuery
  • Reading from SharePoint via OOTB REST service API
    • The list of libraries from my current site is returned and bound to the list on the left (see above picture).  I call it a mini success in setting up the scaffolding.  Will continue another day.
  • Exposes _spPageContextInfo object
  • Expose SP.ClientContext objects/scripts

 

This is the entire project so far:

image

 

Still to come

  • UI for lists
    • Sorting for lists.
    • Determine columns for lists.
  • UI for viewing items
  • UI for editing items
  • ?  Add SPServices?  There are some pretty useful workflow use cases in this library.

 

Call for help!

I think I might be out of my mind on this one.  If you want to join in and hack some JavaScript, yell out and help me out! 

Great opportunity to learn some really cool technology and have a lot of fun!

InfoPath - creating a custom FormServer page to embed your own JavaScript goodness

 

From time to time, people ask about how to embed JavaScript within InfoPath - there are all kinds of reasons why you'd want to do this, and in this example, I'll focus on a previous use case (Disabling backspace key in InfoPath browser form) that I've discussed - to disable the backspace key when you don't have a textbox selected - so that the user isn't dumped back to the previous page in Internet Explorer - a terribly woeful user experience.

Steps

  1. Create a SharePoint solution in VS.NET
  2. Add mapping for Layouts
  3. Copy contents from the OOTB FormServer.aspx file to our custom aspx page
  4. Deploy to see how it works
  5. Add our own, additional JavaScript

 

1. Creating a VS.NET SharePoint Project

 

The key point here is that you will need the CKS extensions for VS.NET 2010.  Grab them first from Extension Manager.

image

Because we are going to build an application page that is deployed into SharePoint Root, this project has to be a farm solution.

image

 

2. Map to _layouts in your SharePoint solution

image

image

 

3. Add our custom aspx page

image

You may get an security warning from VS.NET to trust CKS - allow this.

The Basic Site Page is the simplest page that can be added to a SharePoint solution.  It is essentially one ASPX page without any code behind.  In this example this page is sufficient for our needs.

 

At this point, we should go visit our own SharePoint root and see how the default FormServer.aspx page is built.

Navigate to: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\

And look for FormServer.aspx

You'll see that the page is actually really simple - all the hard work is in the XmlFormView control.  The page passes query parameters to the XmlFormView control.

Copy all the content of this out of the box FormServer.aspx file

Return to our project, and paste all the contents over the sample JLFormServer.aspx file.  Now, your JLFormServer.aspx file should be exactly the same as the out of the box FormServer.aspx file.

image

 

4. Deploy to see how it works

Package and deploy the solution to SharePoint - you'll see this deployed to SharePoint root.

image

 

Take a normal form server url:

http://spg-dev-jl/_layouts/FormServer.aspx?XsnLocation=~site/Forms/Forms/template.xsn&DefaultItemOpen=1

Change it to our custom aspx page:

http://spg-dev-jl/_layouts/JLFormServer/JLFormServer.aspx?XsnLocation=~site/Forms/Forms/template.xsn&DefaultItemOpen=1

image

 

Hey works fine :-)

 

5. Adding our own JavaScript goodness

Go back to our JSFormServer.aspx page, and look for the <head> element.  Let's add some JavaScript.

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js"></script>
<script>
    function document_keydown(e) {

         if (e.keyCode == 8){

            var t = e.target;
            if (t) {
                if (t.tagName == "INPUT") return; // ignore textbox
                if (t.tagName == "TEXTAREA") return; // ignore multi-line textbox
            }
            if ($(t).hasClass("ms-inputuserfield")) {
                return; // ignore people picker, by checking for ms-inputuserfield css class
            }

            // letting us know we've ate a backspace key 
            alert('Ate a backspace key, hew!', false);

            // cancel backspace navigation
            e.preventDefault();
            e.stopImmediatePropagation();
            return false;
        }
    };

    $(document).keydown(document_keydown);
</script>

Package everything and deploy to server.

 

Result: everything in action!

 

Navigate to our custom form server page again.

http://spg-dev-jl/_layouts/JLFormServer/JLFormServer.aspx?XsnLocation=~site/Forms/Forms/template.xsn&DefaultItemOpen=1

Select a textbox and delete a few characters - this should work fine, as the JavaScript function allows this.

Un-focus from a textbox, so that the focus is now on the main page - and press backspace.  Normally, this would trigger Internet Explorer to go back to the previous page in history, but now this event is caught by our JavaScript and cancelled!

image

 

Note

Finally, comment out the alert in your JavaScript - I'm sure you don't want to drive your users crazy.

// letting us know we've ate a backspace key
// alert('Ate a backspace key, hew!');

 

Summary

  • We looked at how to build and deploy a simple site page to SharePoint root
  • What a FormServer.aspx page looks like
  • How we can add additional JavaScript to our Custom FormServer.aspx page

 

Update

  • Updated the javascript function that includes my latest tweaks for multiline textbox and people picker

InfoPath 2010 - query using the REST interface

 

This is an exercise to play with the REST interface, which works extremely well with InfoPath 2010.

Scenario

  1. We have a postcode list.  Filled with post codes and suburbs.
  2. In InfoPath, we want to select a post code and populate the corresponding data from the list.
  3. While this is possible using the old owssvr.dll trick, Let's do this one with the REST interface - which is a much cleaner example.

 

Steps

  1. Here's a very simple custom list, "Postcodes"
    image
  2. The REST interface to select a row, using a filter:
    http://spg-dev-jl/_vti_bin/listdata.svc/Postcodes?$filter=Code eq '2000'
  3. This returns the following XML - you can see Title and Code in the XML
    image
  4. Create an InfoPath 2010 form, create a few fields:  "Postcode" (number) and "Suburb" (text, shown as expression)
    image
    image
  5. Create a secondary data source and connect to the earlier REST service.
    image
  6. Add an action to Postcode - on change, set the REST URL, then execute the query.
    image
    The Change REST URL action appears when you have REST secondary data sources in your 2010 form.

    We want to change the URL based on a formula, so set it to:
    concat("http://spg-dev-jl/_vti_bin/listdata.svc/Postcodes?$filter=Code%20eq%20'", . ,"'")

    image
    image
  7. Finally, copy the new suburb back into our Suburb field from the updated secondary data source.
    image

    image

  8. The completed rule(s)
    image

 

Result

Running in InfoPath rich client

image

Running in Form Server

image

 

Summary

  • The REST data source is actually a FileQueryConnection and expects an XML result.  In InfoPath 2010 though, we have the new action to "change" the path using rules which is really the unsung hero of this story.
  • And thus we got to play with REST and InfoPath 2010

 

Download

https://static1.squarespace.com/static/5527bff2e4b0b430660b0d10/5527c30de4b030eeeef09715/5527c30fe4b030eeeef09eff/1335456086383/RestPostcodesForm.xsn