Translate

Tuesday, August 14, 2012

Contract First Web Services

Preface:

Recently I was thrust into the need to create a new Web Service from scratch, but the client required that the service not be written code first. There are a lot of good arguments on why Contract First development is useful. Here is a chapter on why "Contract First" is preferred, a StackOverflow discussion, and a list of Six Reasons (page is slow to load, but worth it).

I found an MSDN blog that gave be a good middle point to work from, but it didn't contain the entire process from start to finish. So here it is, a three-part walk-through on how to create a .net contract first web service from scratch. Here is an overview of the process:
  • Create a Visual Studio Project
  • Create a WSDL using Altova XMLSpy, and add it to the project
  • Convert the WSDL to a web-service interface
  • Implement and test the web-service with soapUI

Here we go - Create a Visual Studio Project

In Visual Studio 2010, create a new ASP.NET Web Application; I called mine ContractFirstWebServiceExample.

Creating the Visual Studio Project
Now that the solution has been created, it's time to start working on the WSDL. A very good tool for authoring the WSDL is Altova XMLSpy, as mentioned earlier. But before I get into that, think about the specific web service we're going to implement.

The web service will be pretty strait forward, a "Hello Contract First Web Service World" kind of thing. The web service will simply take someones full name as the request, and return a response like "Hello, Abraham Dybvig." The request and response can be a string type:


Simple Web Service Diagram
Now that we know what our web service does, it's time to design a contact for it. In XMLSpy, create a new WSDL file. For this walk-through I'm using a v1.1 WSDL:

Create New Document Dialogue

This generates a stub WSDL with default values. I expanded all nodes on the right panel in this example:

Overview Pane (Expanded)

Edit the details of the WSDL, to names that make sense for the project and save the WSDL in the same folder as the Visual Studio project created earlier. The center pane of XMLSpy now looks something like this (I expanded all the nodes):

WSDL Definition

Here are my modifications:
  • Changed the namespace to http://contract.first.project.namespace
  • Changed the request and response messages to HelloUserRequest and HelloUserResponse respectively
  • Changed the request and response parameters to userName and reply respectively
  • Changed the port to IHelloUserPort (The reasoning for IHelloUserPort is discussed in a later section)
  • Changed the operation to SayHello
  • Changed the binding to HelloUserBinding
  • Changed the service to HelloUserService
One could go on, defining a complete WSDL with imported XSD types, and a robust set of operations in the service. Before the WSDL is published to clients, it can be iterated over in XMLSpy to include more capabilities. Save it to the existing project folder (from earlier) and add it to the Visual Studio project.

WSDL Added to Project
Now that the WSDL is part of the project, we can generate an interface, contained in a .cs file. Visual Studio does not come with a built in tool to create code interfaces from WSDLs, but it can be configured as an external tool by calling SvcUtil. This tool is included as part of the Windows SDK.
  • Add a new menu item, I called it Create WSDL Interface
  • The Command, as of this posting, is located at
    C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SvcUtil.exe
  • For parameters, I used
    /language:C# /out:$(ProjectDir)$(ItemFileName).cs $(ItemPath) /noConfig
    which instructs SvcUtil to create a new C# class file, of the same name as the WSDL in the same directory as the project. Config saving is disabled to prevent UAC errors on Windows 7.
Add External Tool

Once ScvUtil is ready the WSDL can be processed from within Visual Studio. With the WSDL open in Visual Studio, click on the new menu uption Tools/Create WSDL Interface. The results are given in the output window, and a new code file is created in the project folder ready for addition:

Create WSDL Interface
Add the interface to the Visual Studio project and create a new Web Service to implement it.
  • Add the interface .cs file to the project, mine is called IHelloUser.cs
  • Add a new web service to the project, I called mine HelloUserWebService
  • Include and implement the IHelloUserPort interface and add the [WebService] method decoration
The web service is ready for a basic test. Using soapUI to test the service will generate an error response since the method isn't implemented. (For those who prefer TDD, this is expected and encouraged!) Now the service can be fully implemented.

There you have it a soup to nuts walkthrough of contract first web service development. I really enjoyed learning about this the first time trough, and gathering information from various sources (linkes provided in the article).

~AD

P.S. Based on recent experiences working with web services, I have become huge fan of Contract First Web Service Development for a couple reasons. I prefer to use TDD whenever possible and Contract First makes it easy to generate a set of tests for the stub service. One odvious test: does the stub service respond to a soap call (using soapUI, for example) based on the contract WSDL?

Thursday, January 26, 2012

Basic and Advanced Forms for a Single List

Included here, is an old post I began working on at my previous employer while we were researching the usefulness of Infopath 2010. I was unable to finish this post, before transitioning from then to now. As such, I am posting this incomplete blog, as is, so that it might help others realize the full value of Infopath 2010 in their SharePoint projects.

The article is topic complete, all it is really missing is the screen captures to go along with the content...

BEGIN

One great tool that Infopath 2010 offers is different views for the same form. By using two views we can build a form with basic and advanced data entry versions. For this lab I created a list that has seven custom fields. Three number fields for ratings, and a text field for comments.

My intention is to make a simple survey where a user can quickly rate the overall presentation. I also want an optional advanced form to give the presentation seperate overall, content, and presenter scores, as well as leave comments.

After creating the list I have this form by default:

{Picture of Default Form}

As you can see, there are some changes that need to be made. The Title field isn't particularly useful, so I want to automatically fill it with some anonymous data, (See Making Title Fields More Useful with InfoPath 2010). Secondly, I want to keep the function of the number fields, for reporting and metrics, but change their appearance.

I start by customizing the form in InfoPath 2010.

{Picture of InfoPath before customizations}

First I select and delete the entire layout. Here are the customiations:
  • Create a centered page layout with a title, and call it "Rate this Presentation"
  • Add a two column table
  • In the first row, right column, add a custom 3x1 table and set the width of each column to 150px
  • Drag the Overall Rating field control into the first cell of the 3x1 table
  • Delete the label text above the field control
  • Change the control type to a option button
  • Copy and paste the button into the two remaining cells of the 3x1 table
  • Set the properties of the buttons such that the first one's value is 0, the middle to 1 as default, and the right one to 2
  • Enter "Overall Rating" in the label area
  • Use "below expecations," "met expectations," and "exceeded expectations" as descriptive text next to each option button
  • Delete remainint rows of the main table
  • Add two buttons to the form called "Advanced" and "Submit" respectively
The form should look something like this:

{Picture of WIP Form}

Now we need to create a new view for the advanced version of the form. Start by clicking "New" in the Views section of the Page Design tab.

{Pic of the New View button in action}

I called my new view "Edit item (advanced)." Copy the contents of the default view into the advanced view to use as a starting point. Here are the rest of the edits:
  • Add three rows to the main layout table
  • Create "Content Rating" and "Presenter Rating" controls similar to the existing "Overall Rating" control (Short-cut! Copy and paste the existing table and controls and just change the binding property to the correct field)
  • Add the Comments field controls to the last row of the layout table
  • Change the "Advanced" button to "Basic"
The new view looks something like this:

{Picture of the advanced view}

Now we need to connect the rules to the buttons. Switch back to the basic (default) view and bring up the rules manager for the "Advanced" button. Add a new action rule to tbe button and give it a name, "Advanced Clicked" will do. Add an action to switch views to the "Edit item (advanced)" view. Verify that the Submit button is set to submit the form.

{Picture of switch item rule dialogue}

All that remains is to configure the basic button on the other view. Switch to the advanced view and add a new rule to change views back to the default edit item view. Double check that the Submit button is submitting the form and we're all set to publish the form to the list.

Here is what my advanced form looks like in SharePoint:

{Picture of finished advanced form}

You might notice that whatever you set "Overall Rating" to is maintained when you switch between basic and advanced forms. Indeed, all the fields values are kept and saved on submit, even when not shown in the form. This hints at the possibility of building a multi-page form to fill out a complex list entry - but I think I'll save that for another time.

END

Friday, June 25, 2010

FBA Users in SharePoint 2010

One of our sites scheduled for upgrade to SharePoint 2010 uses Forms Based Authentication (FBA). Various blogs can be found on how to set up SharePoint 2010 to connect to a FBA database. But, one critical difference is how the new Claims Based Authentication (FBA in SP2010 speak) hands over an Idenentity to SharePoint 2010.

The change from integrated security to a Claims Based is basically this: In Claims Based mode, the SharePoint site no longer handles verifying Identities; that is handled through the new Security Token Service (STS). Previously a user's integrated FBA Identity was something like "FBAMembership:EtherDragon" now, in 2010, the STS hands over my Identity with something like "i:0#.f|FBAMembership|EtherDragon" and, as far as 2010 is concerned, that is a different user.

The fix was to write a quick Web Part for 2010 that replaces all FBA user Identities in all groups with the correct STS one.

Here's some code:
(Code)
SPWeb oWeb = SPContext.Current.Web;

foreach (SPGroup myGroup in oWeb.Groups)
{
string wrongFormat = "fbamembership:";
SPUserCollection myUsers = myGroup.Users;
List usersToDelete = new List();

foreach (SPUser userCandidate in myUsers)
{
if (userCandidate.LoginName.Length >= wrongFormat.Length)
if (userCandidate.LoginName.Substring(0, wrongFormat.Length) == wrongFormat)
{
usersToDelete.Add(userCandidate);
}
}

foreach (SPUser myUser in usersToDelete)
{

string loginName = "i:0#.f|fbamembership|
" + myUser.LoginName.Substring(wrongFormat.Length);
string eMail = myUser.Email;
string name = myUser.Name;
string notes = myUser.Notes;

myGroup.RemoveUser(myUser);
myGroup.Update();
myGroup.AddUser(loginName, eMail, name, notes);
myGroup.Update();
}
}
(End Code)

Without this little code block, we would have had to go through about 2000 user entries in various groups to remove and replace the users through the SharePoint UI.

Wednesday, May 5, 2010

"The specified file is not a valid spreadsheet or contains no data to import"

Here's the problem:

You try to create a custom SharePoint list using the Import Spreadsheet function and get an error, "The specified file is not a valid spreadsheet or contains no data to import"

The problem is that IE doesn't have access to your file system, and in this instance, it needs it. The solution is to add the SharePoint site to your Trusted Sites zone.

Go to Tools / Internet Options
Click on the Security Tab, hightlight Trusted Sites and click the Sites button.
Enter the URL of the SharePoint site and click the Add button.
Close and Save your settings. You can now impor the spread sheet.

Wednesday, March 24, 2010

Making Title Fields More Useful with InfoPath 2010

One of the challenges 4QTRS has had was determining how to best use the “Title” field in a given SharePoint list. Many lists, such as “Tasks” can use “Title” very naturally, using the title to give a few words to describe the item; i.e. “Run Server Updates.” But, other titles don’t make a lot of sense. “Last Name” is a field that can be adapted for the title field, indeed, the contact list changes the title field display name to “Last Name” for readability.

 
Consider a simple in/out log. The list leverages the already existing “Created By” field to determine who records in/out status, as well as the existing “Created” date/time field to log the in/out change. In this case, having a person enter anything into the “Title” field would be superfluous and open the process up to errors. So, we’re going to have the form automatically populate the title field and hide it from the user.

 
Start by opening up InfoPath 2010 and creating a new SharePoint List Form.

 

After authenticating to the site, and entering “InOutBoard” as the new list name, we see the default InfoPath form. Add a field called “Presence” and change the choices “In” and “Out” only.

 

Next, we will simplify the form to an easy two-button layout using the InfoPath designer. Our new buttons will each have a rule that runs on click that will handle all the work for us, including making sense of the otherwise useless title field.

 
Start by wiping the form, and creating a new centered layout section. Place a simple table within the layout and add two buttons; one each in the left and right cells. Change the buttons to read “In” and “Out” and delete the remaining table rows. Your form should look like this:


 
Now, we need to add four rules to the In button to complete the data entry.
  1. Set a field’s value: Presence = “In”
  2. Set a field’s value: Title = concat(userName(), " In at ", now())
  3. Submit using data connection
  4. Close this form

Configure a similar set of rules for the Out button, changing the two occurrences of the word “In” to “Out” and publish the form.

 
Click the Add new item link bring up the new form. We can click either button to enter an in/out log item into the list. Most importantly, the title field populates with useful information; “etherdragon In at 2010-03-24T11:25:39”

 
Improving the form further by changing the simple buttons to image buttons. Here is my finalized form using two simple image buttons.

 

Tuesday, December 15, 2009

SharePoint View Filter order of precedence.

SharePoint Queries order of precedence.

WSS has the ability to build complex ad-hoc views of list data. But, configurators often run into strange results when mixing “and” and “or” operations in the filter section of the view.

Consider this example:

I want to create a view called “Overdue Tasks” which will display only those tasks that do not have a “Completed” status. I also want to limit the view to items with a due date that is either null or before today.

In a logical form, I’m looking for:
(Status <> Completed) AND ( (DueDate = null) OR (DueDate < Today) )

If I here to hand-write a CAML query (see http://msdn.microsoft.com/en-us/library/ms467521.aspx) it might look like this:
I used the following data set to make sure I configured the view correctly:

Given my logical conditions and the above dataset, I can expect to see two entries returned from the query: “Not Complete and Late” and “Not Complete no Due Date”

Initially, I tried to configure this query like so:
And got these incorrect results:

Reviewing examples above you can see that the order of precedence is important. I want WSS to consider the OR operation before considering the AND operation. It turns out the Edit View tool makes this simple if we remember a couple simple rules.

1. All logical operations occur from top to bottom.
2. Earlier logical operations are nested within later logical operations.

If I examine my logical form for the previous filter settings, I can immediately see my error.
( (Status = Completed) AND (Due Date = null) ) OR (Due Date = Today)

I need to restructure my logical form with the above rules in mind. Doing so produces this:
( (DueDate = null) OR (DueDate < Today) ) AND (Status <> Completed)

Which leads me to configure the view like this:
And get the expected results:


Indeed, pulling the CAML query returns the following:

Notice that the only real difference between the initial hand-written query and the WSS-generated one is the Neq clause moved from the beginning of the query to the end. The Neq clause is still nested within the And clause, but after the Or clause (which doesn’t cause any problems because the “And” operation is commutative. See http://en.wikipedia.org/wiki/Commutativity).

Happy view building!

~ED

Thursday, December 3, 2009

Configuring FTP on Windows 2008

Earlier this week, I set up a new server with Windows 2008 x64 Enterprise to use with Windows SharePoint Services (WSS 3.0). In order to upload our custom solutions I had to enable FTP through IIS v6. Everything seemed straight forward. I could connect to FTP with appropriate credentials but could not list contents or upload new items.

The problem was that random ports used by FTP could not get through Windows Firewall. An article at http://support.microsoft.com/kb/832017 explains how FTP uses the default dynamic ports from #49152 to #65535.

One solution would be to manually open each and every port in the Windows Firewall exceptions. The tedium of this solution would surely lead to madness.

The solution I implemented was to limit the number of passive connections available, specify which ports are to be used, and allow those ports through the firewall.

In IIS v6 Manager, I brought up the properties for my FTP server.


I ensured that “Enable Direct Metabase Edit” is checked and clicked OK.


Next I ran a short script that designated which ports FTP Passive will use. The script also automatically added the ports to the Windows Firewall exceptions.

I pasted something like this script into a .bat file and ran it (I changed the port ranges to protect the innocent). It’s an adaptation of a script found at http://www.tino.nl/index.php/2008/12/19/passive-ftp-on-windows-server-2003-with-windows-firewall/

[begin code]
ECHO Udating FTP Registry Values
C:\Inetpub\AdminScripts\adsutil.vbs set /MSFTPSVC/PassivePortRange "42000-42199"
ECHO OPENING FIREWALL PORTS
FOR /L %%I IN (42000,1,42199) DO NETSH FIREWALL ADD PORTOPENING TCP %%I FTPPort%%I
iisreset
ECHO FINISHED
Pause
[end code]

Upon inspecting Windows Firewall, I confirmed that the ports had been correctly added and I was able to connect with an FTP client.

This process has some security benefits:
1. It allows you to designate a non-standard port for FTP if you wish
2. You can control exactly which FTP Passive ports to use, requiring fewer ports to be open through the firewall.

Happy FTPing!