Partager via


Getting Started Building a WCF Web Service

This post is the first in a series of upcoming MSDN articles on creating a claims-aware web service and consuming it from SharePoint BCS.  In the short time that I’ve worked with claims-based authentication, what I experience is that while there are not very many steps to get it working, if you get anything wrong, then it just doesn’t work, and it takes some effort to figure out the problem.  My approach in these articles is to supply some procedures with small steps, with instructions all along the way to validate that what you have done so far works properly.  So the first step is to create a WCF web service, host it using IIS, and validate that it is working.

This blog is inactive.
New blog: EricWhite.com/blog

Blog TOC

Getting Started Building a WCF Web Service (This post)

Shows how to create a very simple web service using WCF.  Shows how to host this web service using IIS.

Determining Caller Identity within a WCF Web Service

Enhances the example so that the Web service can authoritatively report on the identity of its caller.

Establishing Trust between a WCF Web Service and the SharePoint 2010 Security Token Service

Configures the example developed in the previous article so that it uses a self-signed certificate to support a secure connection.

Consuming a Claims-Enabled WCF Web Service as an SharePoint 2010 External Content Type

Walks through the procedure for consuming a claims-enabled web service as a SharePoint 2010 External Content Type.

These articles were written by Saji Varkey, and Bin Zhang, and me.  They will be published on MSDN sometime in the near future.  After they are published, I will update these posts to point to the MSDN articles.  Juan Balmori Labra was the program manager behind these articles.

This post shows how to create a very simple web service using Windows Communications Foundation (WCF).  There is one special characteristic of the web service that I present in this article, which is that while it is very simple, it can be consumed as an External Content Type (ECT) from Business Connectivity Services (BCS).  In addition, the procedure presented in this post shows how to host this web service using Internet Information Services (IIS).

This web service contains only two methods: a ‘finder’ to retrieve a collection of items, and a ‘specific finder’ to retrieve a single item.  The ‘database’ behind the collection is just an initialized list.  The ‘schema’ of this little ‘database’ is very simple.  It is a single flat table consisting of two fields – an integer CustomerID, and a string CustomerName.  CustomerID is a unique ID.

return new List<Customer>()
{
new Customer
{
CustomerID = 1,
CustomerName = "Bob",
},
new Customer
{
CustomerID = 2,
CustomerName = "Bill",
},
new Customer
{
CustomerID = 3,
CustomerName = "Cheryl",
},
};

After building and configuring this web service, you can use SharePoint Designer 2010 to create an ECT from it, and then view the data in a SharePoint list.

As you probably know, BCS in SharePoint server 2010 is read/write.  If you supply additional methods to create, update, and delete items, then you can fully maintain the data in a list.  I’m interested in keeping this web service absolutely as simple as possible, so this is only a read-only implementation.  My focus will be completely on the security and identity issues.  How the database is stored, where it is stored, or the details of the schema are irrelevant to the topic at hand.

The procedure presented here is for Windows Server 2008 R2 and Windows Server 2008.  You can build this web service using either Visual Studio 2010 or Visual Studio 2008.

You can build, run, and test the web service presented in this post on any development computer that is running IIS.  However, if you want to connect to this web service as an ECT using BCS, then build this example on a SharePoint 2010 development machine, so that the SharePoint 2010 server and the example web service are running on the same computer.  You can put this web service on a different machine, and consume it as an ECT, however, in that situation, you must either remove security, or you need to create a claims-aware web service.

As I mentioned, the procedure that I present here shows how to host the web service under IIS.  This is the way that most implementers of such a web service will want to host it.  Hosting it as a service of IIS gives lots of benefits such as process recycling, process health monitoring, and message based activation.

Building the Example

This procedure is for Windows Server 2008 or Windows Server 2008 R2.  In both cases, I started on a machine that had a fresh, patched install of the operating system.  I then installed the necessary roles and features so that Internet Information Services (IIS) was installed and running.  In addition, the procedures presented in this post require the .NET Framework 3.5.1, and either Visual Studio 2008 or Visual Studio 2010.

Installing WCF and IIS

Use Server Manager to install the Web Server (IIS) Role and the .NET Framework 3.5.1 feature.

To run this example, the only Role that is required is Web Server (IIS) .

After adding the Web Server (IIS) role, the Roles wizard will ask you to select Role Services.  Select Application Development.

To install the .NET Framework, add the .NET Framework 3.5.1 Features.

When you are installing this feature on Windows Server 2008 (not R2), after selecting the .NET Framework 3.0 Features, select WCF Activation.  This is selected by default on Windows Server 2008 R2.

Both WCF and IIS must be installed for IIS-hosted WCF services to function correctly.  The procedures for installing WCF (as part of the .NET Framework 3.0) and IIS vary depending on the operating system that you are using.  If you are installing on an operating system other than Windows Server 2008 or Windows Server 2008 R2, see Microsoft .NET Framework 3.0 Redistributable Package to download and install the .NET Framework 3.0.  See Installing IIS for further instructions in that area.

Registering the Service Model

To run this example, you need to register this version of WCF and update scriptmaps at the IIS metabase root.

1.       Start a Visual Studio Command Prompt.  Run as administrator.

Click Start => All Programs => Visual Studio 2010 => Visual Studio Tools => Visual Studio Command PromptRight-click, select Start as Administrator.

The Visual Studio command prompt is located in a similar place for Visual Studio 2008.

2.       Change directory to:

c:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation

Enter:

cd "c:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation"

3.       In the command prompt, enter:

ServiceModelReg -i

This didn’t need to be a Visual Studio command prompt, but the following step needs a Visual Studio command prompt, so for efficiency, I created one in this step.

Updating Script Maps

4.       In the command prompt, enter:

aspnet_regiis.exe -i

Creating a Web Service

1.       Create a directory, C:\MyWebService, which will contain the web service.  If you use a different directory than this, you will need to alter these procedures as appropriate.

2.       Start Visual Studio 2010 (or 2008).

3.       Click File => New => Project.

a.       For the installed template category, select WCF.

b.      For the template, select WCF Service Application.

c.       Target the .NET Framework 3.5.

d.      For the location of the project, browse to the directory that you created in step 1.

e.      Name the project CustomersService.

f.        Do not create a directory for the solution.

Note: Don’t forget to target the .NET Framework 3.5. By default, Visual Studio will target the .NET Framework 4.0, and you must change to 3.5 for the procedure presented here to work.

4.       In the project, rename IService1.cs to ICustomers.cs.  Visual Studio 2010 will ask whether you would also like to perform a rename in this project of all references to the code element ‘IService1’?  Click Yes.  Actually, we’re going to replace all code in all modules, so it doesn’t matter whether you click Yes or No.

5.       In the project, rename Service1.svc to Customers.svc.  After renaming these items, the Solution Explorer will look like this.

6.       Replace Customers.svc with the following single line of markup.  Right click on Customers.svc, and select View Markup.  Copy, paste, and save.

<%@ ServiceHost Language="C#" Debug="true" Service="CustomersService.Customers" CodeBehind="Customers.svc.cs" %>

7.       Replace Customers.svc.cs with the following code.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CustomersService
{
public class Customers : ICustomers
{
// Finder
public List<Customer> GetAllCustomers()
{
return new List<Customer>()
{
new Customer
{
CustomerID = 1,
CustomerName = "Bob",
},
new Customer
{
CustomerID = 2,
CustomerName = "Bill",
},
new Customer
{
CustomerID = 3,
CustomerName = "Cheryl",
},
};
}

// Specific finder
public Customer GetCustomerByID(int CustomerID)
{
return GetAllCustomers().FirstOrDefault(c => c.CustomerID == CustomerID);
}
}
}

8.       Replace ICustomers.cs with the following code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace CustomersService
{
[ServiceContract]
public interface ICustomers
{
[OperationContract] //finder
List<Customer> GetAllCustomers();

[OperationContract] //specificFinder
Customer GetCustomerByID(int CustomerID);
}

[DataContract]
public class Customer
{
[DataMember]
public int CustomerID { get; set; }

[DataMember]
public string CustomerName { get; set; }
}
}

9.       Replace Web.config with the following markup.  In Solution Explorer, right-click on Web.config and select Edit.  Copy, paste, and save.  Important note: this is the Web.config that configures this specific web service.  It resides at C:\MyWebService\CustomersService.

<?xmlversion="1.0"?>
<configuration>
<system.serviceModel>
<services>
<servicebehaviorConfiguration="CustomersService.Service1Behavior"
name="CustomersService.Customers">
<endpointaddress=""binding="wsHttpBinding"contract="CustomersService.ICustomers">
<identity>
<dnsvalue="localhost" />
</identity>
</endpoint>
<endpointaddress="mex"binding="mexHttpBinding"contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behaviorname="CustomersService.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadatahttpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebugincludeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

10.   Build the application.

11.   Add an application to the default web site.

a.       Start Internet Information Services (IIS) Manager.  Click Start => All Programs => Administrative Tools => Internet Information Services (IIS) Manager.

b.      In Internet Information Services (IIS) Manager, expand Sites, and right-click on Default Web Site, and select Add Application.

 

c.       In the Add Application dialog box, in the Alias field, enter Customers.  In the Physical Path field, browse to C:\MyWebService\CustomersService.  Click OK twice.

12.   Validate that the web service is running.  Start Internet Explorer, and browse to https://localhost/Customers/Customers.svc.  If the web service is running, you will see the following:

Another interesting approach to testing the Web service is to use the WCF test client.  Start a Visual Studio command prompt (or use the one that is open from the beginning of this procedure).  Enter wcftestclient to run the WCF test client.  Click File => Add Service.  Enter https://localhost/Customers/Customers.svc as the endpoint address, and click OK.

If the service was added successfully, you will see the methods that the service exposes.

Double-click on GetAllCustomers.  This opens a window that allows you to configure the request and invoke the request.  Click on Invoke to see the response from the Web service.

In the next article, we will add some Windows Identity Framework (WIF) features, which we can use to determine the identity of the caller.

Comments

  • Anonymous
    December 07, 2010
    I got the following error: System.InvalidOperationException: The type 'CustomersService.Service1', provided as the Service attribute value in the ServiceHost directive could not be found. The application is pointing to the right directory. The DLL is present inside the bin folder. All the files are inside C:MyWebServiceCustomersService Not sure what's going on.

  • Anonymous
    January 13, 2011
    @WCF wouldn't run: Check the Customers.cs and Customers.svc files, and make sure you followed steps 5 and 6 in this article. I bet you'll see the Services attribute needs to be updated, and possibly the class name as well. @Eric: Thanks for this series!

  • Anonymous
    July 14, 2011
    Hi Eric, I have set up claims aware WCF and SharePoint as you mentioned and seeing an expception in the WCF Service Log: Message security verification failed. The X.509 certificate CN=SharePoint Security Token Service, OU=SharePoint, O=Microsoft, C=US chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain could not be built to a trusted root authority. Could you please tell me what i am doing wrong? Thanks Dathu

  • Anonymous
    November 02, 2011
    The comment has been removed

  • Anonymous
    January 18, 2012
    Great Article! Really helps to pen out the process. However, it could really do with some explinations on the different methods and objects being used, i.e. the difference between an OperationContract and a DataContract. Thanks for the help though!

  • Anonymous
    January 27, 2012
    I wanted to deploy the incoming wcf service request which I get on server1 to another server2 can you please give me a example or any good solution