HiddenNetwork.com Banner
Showing posts with label InfoPath. Show all posts
Showing posts with label InfoPath. Show all posts

Wednesday, June 06, 2007

Allowing InfoPath forms to redirect to pages in other site collections

In InfoPath 2007, when you publish a form as a web form, you have the option to specify several query string parameters. One of those parameters is the "Source" parameter, which is "The location to which the user will be redirected when the form is closed. The URL must be in the same site collection or an error will be returned."
The error mentioned is "The following location is not accessible, because it is in a different site collection:" and the url you specified.

So it seems that specifying a source from another site collection is impossible. But what if I have a site collection dedicated to forms? lets say "http://forms", to which I link from the intranet home page or another page, and I want that when the user closes the form, he will be redirected back to the page in the intranet (lets say "http://intranet") that we started from?

I had to come up with a solution, and a simple one jumped to mind - a redirect page!
The trick is simple. Instead of specifying a link to "http://intranet" as the source parameter (which will cause an error), specify a link to a special page in the layouts folder, and give that page the query string that links to the page you want to return to.

Confused? here is an example:
Instead of linking to the form with this link:

http://forms/_layouts/FormServer.aspx?XsnLocation=http://forms/myforms/Forms/template.xsn&Source=http://intranet

Link to it like this:
http://forms/_layouts/FormServer.aspx?XsnLocation=http://forms/myforms/Forms/template.xsn&
Source=http://forms/_layouts/SPSTipsFormRedirector.aspx?target=http://intranet

As you can see from the links, the first one will cause an error because we are linking to another site collection, while the second one will work, because we are linking to the current site collection.

So the only thing left for me to show you is how to create the SPSTipsFormRedirector.aspx page that will handle the redirect to the page you specified in the red section in the second link:
Open your layouts folder (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS) and create a new text file by the name SPSTipsFormRedirector.aspx. Open the file in a text editor such as notepad, and copy the following code:

<%
string target = Page.Request.QueryString["target"];
Page.Response.Redirect(target);
%>
<%
@ Page Language="C#" Inherits="System.Web.UI.Page" %>
<html>
</
html>

Repeate this in every front end server, and you are ready to write links to forms that, when closed, will go back to a page you specify in the link!

Wednesday, February 14, 2007

Publishing Infopath To SharePoint: "the following url is not valid" Error

I spent nearly a week of work before I got this error figured out.

I was trying to publish a form that I succesfully published to all development servers to a test server. Every time I tried to publish it would say "the following url is not valid" when I entered the path to the sharepoint site.

Searching the internet, I found some possibilities, but none worked. For the sake of people who encounter this error, I will outline my troubleshooting recommendations below:

  1. Make sure the sharepoint application that contains the site you are publishing to has a site in the root.
    That was my mistake (mistake?). If you create all the sites under a virtual path such as "/sites/", infopath cannot publish.
    So make sure there is a sharepoint site on the "/" path.
  2. Create a new SSP.
    I have no idea why, but people on the internet claimed this solved the problem they had.
  3. If the sharepoint in question is of version 2003, uninstall .NET2 from the server. Again, no explanation was given, but one post in the news groups claim it solved their problem (and probably started a lot of others...)

Monday, January 22, 2007

InfoPath form Services - implementing a Master-Detail on the web

If you ever tried publishing a form to the web using infopath form services, you probably know that one compatibility issue you will have is with master-detail (also known as "cascading dropdowns") fields.

Master-detail basically means when you have two fields (usualy dropdown boxes) and you want the options in the second field to change based on the choice the user made in the first field.

For example, I have a dropdown called "States", and a dropdown calles "Cities". Now I want when the user chooses a state, to only show cities within the chosen state.
This is easy to do in infopath - just connect the dropdowns with a little configuration. But when you try to publish the form to a web form, it will tell you that the master-detail will simply not work in the web form. It's not supported.

To the rescue!
Let me use the above example, showing you how to get it to work.
First, you will need to set up two seperate data connections - one for the states, and one for the cities. I will use sharepoint lists in this example (and on the way tell you a small trick that my colluege Rai Umair showed me).
Lets create the lists:

The states list


Set up a lookup into the states list from the cities list


The cities list

Now that we have our lists set up, lets build a simple infopath form that will show them:

  • Create a blank new form in infopath
  • Add the connection to the "States" list:
    Tools->Data Connections->Add->Receive Data->SharePoint library or list->link to the site->Select "States"->Select "Title"->click next until the wizard finishes.
  • Add the connection to the "Cities" list:
    ok, here is the trick from Rai. instead of adding the connection to the list as a sharepoint library connection, we will instead add it as a XML connection, and point it to a url that will allow us to filter the list. This is a nice trick and I thought you should see it. The whole idea is to set up a connection that will be able to filter based on a user selection. if you have other methods of doing that, feel free.
    • First we need to find out the GUID (the id) of the cities list. To do that, open the cities list in the browser, and click on "Settings"->"List Settings". The id of the list is in the address bar - after the bit that says "?List=".
      For example, if the address bar shows
      "http://server/infopath/_layouts/listedit.aspx?List=%7B7DF67EB0%2D723A%2D4897%2DA461%2D09EA9CC0D90C%7D"
      that means the ID is the bit painted in red.
      But, if you will note, it is url-encoded. you will need to replace "%7B" with "{" and "%7D" with "}" and "%2D" with "-" so the end result is: {7DF67EB0-723A-4897-A461-09EA9CC0D90C}
    • Once you have the ID, use it to construct a url like this:
      http://server/infopath/_vti_bin/owssvr.dll?Cmd=Display&List={put the ID here}&XMLDATA=TRUE
      Example: http://server/infopath/_vti_bin/owssvr.dll?Cmd=Display&List={7DF67EB0-723A-4897-A461-09EA9CC0D90C}&XMLDATA=TRUE
      If you open it in Internet Explorer, you should see something like this:

      This gets us the content of the cities list in an XML format that Infopath knows how to read.
    • Go back to infopath, add a new datasource ->Receive Data->XML Document-> paste the path we constructed above->choose "Access the data from the specified location"->Give the data connection a name (Cities) and clear the "Automatically retrieve data when form is opened" (important!)
  • Your data sources screen should now contain two data sources:
  • Lets add two fields into the main data source - City and State:
  • Lets add the two fields to the form as drop downs:
  • Change the properties of the "State" drop down to get the values from the states data source:
  • set up the properties of the city in the same fashion:
  • Ok, test the form. The states drop down should show the states, while the city dropdown should be empty since we told the datasource not to load the values on form load.

Now that our form is ready, all we need to do is make sure that when a user picks a state, the form loads the cities. Again, it would have been a simple task if we didnt want to publish the form to a web form, but since we do - we will have to do it by code.
Small note - my code is in C#, and by default Infopath is set to use VB.NET. I suggest that you change the setting for this form - open Tools->Form Options->Programming, and select C# as template code language.
While you are in the tools->options, you may as well set the compatibility to "Design a form template that can be opened in a browser or infopath"

Right click the "State" dropdown, and select "Programming"-"Changed Event":


Visual studio has opened, with an empty new event "State_Changed". Paste the following code into the module

public void State_Changed(object sender, XmlEventArgs e) { SetCitiesOptions(); } private void SetCitiesOptions() { FileQueryConnection q = (FileQueryConnection)this.DataConnections["Cities"]; q.FileLocation = q.FileLocation + "&FilterField1=State&FilterValue1=" + GetStateValue(); q.Execute(); } private string GetStateValue() { XPathNavigator nav = this.CreateNavigator(); string filterValue = (string)nav.SelectSingleNode("/my:myFields/my:State", this.NamespaceManager).ValueAs(typeof(string)); return filterValue; }

So, what does this code do?

  • The "GetStateValue" function simply uses the XPathNavigator to get the value the user selected in the "State" field. We can also get that from the "e" object of the event, but to simplify the readability of the code I used functions here.
  • The "SetCitiesOptions" changes the url of the XML file that the cities data connection is using, and adds a filter to it. the filter syntax is "FilterField1=[name of field]&FilterValue1=[Value you want to filter".
    So basically, you can create whatever filter you want on the fields, and as many filters as you want (in an "And" chain).
  • The changed event for the states just makes sure the form loads the city data with the appropriate filter!

this will work on the client side, but not on the server side. why? because we are doing the re-query by code, the server will not refresh the page (postback). So to force a post back you will have to add a rule to the "State" dropdown. The rule will force the page to get the new information.
To do that, right-click the "State" dropdown, and choose "Rules" from the menu. Click "Add" to create a new rule and then "Set Condition" to "State is not blank" and add an action "query using a dataconnection" from cities:


How easy is that?

Try and preview you'r form in infopath. Now when you select a state, the cities box should show options based on the selection you made:


Now publish the form to a sharepoint forms server. Since this is a long proccess, and there are enough articles about this on the net, I will leave you to it.

When you test your form on the web, it should cascade the field:


You will note that the refresh is done using AJAX, so the page does not postback, but instead just waits for a second (with a nice bar) and then populates the data.

References and thanks

  • I want to thank my colleague Rai Umair for the "/_vti_bin/owssvr.dll" trick. May he resume blogging again soon.
  • I want to thank Ed Torres for forcing me to take a look at this and listening to me complain as I tried to make this work.
  • While I was writing this article, a colleague (Lee Marriage) sent me a link to an article doing something very similar by Scott Heim from Microsoft's Infopath team. His solution is to use a web service to filter the list items (I like Rai's trick better. no code needed, and easier to deploy) and using a similar rule like I did to refresh the data.

Monday, January 01, 2007

InfoPath Form Services Best Practices- The View State

If you havent read the technet article on infopath form services best practices, now is the time.
However, The article gives some advice about something called the "form view" and doesnt specify where to set it. So to help you find it - here is where.

In central administration, open the "application management" page, and under the "Infoopath Forms Services" section you will find a link "Configure Infopath Form Services".
The bottom of the page contains two options - Session state service and Form view.

Now, if you had read the technet article on infopath form services best practices (you mean you still didnt? why not?) you will know the difference between the two - the form view reduces database load. it puts everything on the client side, and that means that a lot of data is sent between the client and the server each time something happens on the form.
This is recommended if you dont have bandwidth problems in your environment, because your SQL server will have less load on it. However, if your deployment is such that you have poor connections for some of the users, I suggest you either set session state, or set a low number of kilobytes in the form view maximum box.

You should note that session state service is turned off by default on the server. You must set up a shared service provider first, and then enable it (application management page - configure session state). You may also need to allow it in the web.config file (see my previous article on the subject).