WCF

...now browsing by category

 

Created a self-signed certificate for WCF development – Windows 2003

Tuesday, July 12th, 2011

During the development of a WCF app, I needed to issue a self-signed certificate to my local Windows 2003 server in order to test out ways to secure WCF server-client communication. For IIS6 this was a bit trickier than IIS7. I needed to download the IIS6 resource tool kit and then run selfssl.exe to create the certificate. IIS7 could do it right on its GUI. Here were the detail steps that I went through to create a SSL-enabled hosting environment (via certificate) on my local development machine (credited this very useful posting here):

  1. Downloaded IIS6 resource kit from here http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=17275 and installed it.
  2. Start ->All Programs -> IIS Resources-> SelfSSL
  3. This launched into command line:C:\Program Files\IIS Resources\SelfSSL>selfssl /N:CN=localhost:8088 /K:1024 /V:365 /S:437690215 /T
    Explanations:

    • localhost:8088 – this is where the https site is to be hosted; as port 80 already taken by another web host, I used 8088 for the new site;
    • /K: is the key size – 2048 is recommended (but 1024 worked for my case);
    • /V: days of validity – 365 is recommended (I actually used 730 or 2 years for development convenience)
    • /S: number for your web site identifier in IIS (437690215 is site id for Wcfhost, default website usually is 1, found it under the root of the website property)
    • /T makes the certificated trusted
  4. Answered “Y” at the next prompt.
  5. The message:”The self signed certificate was successfully assigned to site 437690215″
    Go back to IIS6 and now there is a Certificate under the Directory Security

For creating a self-signed certificate in IIS7, follow this article at MSDN. http://msdn.microsoft.com/library/ff406125.aspx

Consume WCF service from .Net 1.1

Sunday, January 2nd, 2011

I have struggled for the past week not being able to consume a ASMX service exposed through a WCF service app that was created on .Net 4.0 and Entity Framework. The key to make a WCF service consumable by legacy .Net app was to expose the service as an old fashion ASMX, through adding a XmlSerializerFormat attribute while building the ServiceContract interface, as shown in this sample:

[ServiceContract, XmlSerializerFormat]

public interface IService1

{

[OperationContract]

string GetData(int value);

 

[OperationContract]

CompositeType GetDataUsingDataContract(CompositeType composite);

 

}

 

The second key step was to make sure the web.config of the WCF service project would use “basicHttpBinding” and set endpoint address to “basic” type. When I first started out, many cited the reference from MSDN at http://msdn.microsoft.com/en-us/library/ms751433.aspx; I followed the example, and still got the “Underneath connection had been closed” error. Today, I came across another posting at http://social.msdn.microsoft.com/forums/en-US/wcf/thread/1f8c7fe9-784c-4beb-8d0f-060bf8bfc24f and that had liberated me from wondering why this damn thing not working – well, the web.config example in the MSDN article had an empty string in the address field while this social.msdn positing had a “basic” in the enpoint address;  I tried that and it worked this time! Thanks Jay R. Wren who answered a user’s question at social.msdn.com.

 

Here was the endpoint configuration that worked on my case:

<service name=”WcfService1.Service1″  behaviorConfiguration=”AsmxBehavior”>

<endpoint address=”basic” binding=”basicHttpBinding” contract=”WcfService1.IService1″></endpoint>

 

The entire web.config file that is in the WCF app project that will generate the ASMX service to be consumed by .Net 1.1 client is as below:

<?xml version=”1.0″?>

<configuration>

<system.web>

<compilation debug=”true” targetFramework=”4.0″ />

</system.web>

<system.serviceModel>

<services>

<service name=”WcfService1.Service1″  behaviorConfiguration=”AsmxBehavior”>

<endpoint address=”basic” binding=”basicHttpBinding” contract=”WcfService1.IService1″></endpoint>

</service>

</services>

<behaviors>

<serviceBehaviors>

<behavior name=”AsmxBehavior”>

<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>

<serviceMetadata httpGetEnabled=”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 –>

<serviceDebug includeExceptionDetailInFaults=”false”/>

</behavior>

</serviceBehaviors>

</behaviors>

<serviceHostingEnvironment multipleSiteBindingsEnabled=”true” />

</system.serviceModel>

<system.webServer>

<modules runAllManagedModulesForAllRequests=”true”/>

</system.webServer>

 

</configuration>

 

Mysterious connection error in WCF web service call

Thursday, October 14th, 2010

While working on a WCF Service call to return an e-commerce order object to a web client , I sometimes got this puzzling error inside client code:

“The underlying connection was closed: The connection was closed unexpectedly.”

At the beginning, I thought this must be something to do with Entity connection or some SQL to Entity operations inside the data tier that was built on ASP.Net Entity Framework; but there was nothing to be found there.

Then I searched and visited many web postings, and most of them pointed to configuration problem with WCF service model’s endpoint settings. I even followed some postings and made the corresponding changes; but this dreaded error still lingered. I was about to give up before I realized that the WCF service call was working fine before I added couple of enumerated class members to the DataContract class that is to return. Here was the class that was built into my WCF services layer and to be returned to client when the service method “GetOrder” was called:

 

[DataContract] public class EcommOrder : SalesOrder

{

[DataMember] public int EcommOrderID { get; set; }

[DataMember] public int EcommOrderTypeID { get; set; }

// … more data members

}

//web service method call

public EcommOrder GetOrder(int orerid)

{

EcommOrder returned=new EcommOrder();

//retrieve order from data tier (EF) and populate the object

return returned;

}

On the client side where the service was invoked, the serializable object EcommOrder was fetched good and sound.  Then I added this enum member to the EcommOrder class inside the Service tier:

[DataContract] public enum OrderTypes

{

[EnumMember]

StudentOrder=1,

[EnumMember]

CorporateOrder=2,

//and so on

 

}  and EcommOrder now looks like :

 

[DataContract] public class EcommOrder : SalesOrder

{

[DataMember] public int EcommOrderID { get; set; }

[DataMember] public int EcommOrderTypeID { get; set; }

[DataMember] public OrderTypes EcommOrderType;

// … more data members

}

Then I went back to the client code and call the same service call to return the modified EcommOrder object: Oops, now I got that dreaded and misleading error:

“The underlying connection was closed: The connection was closed unexpectedly.”

To confirm the Enum was the cause, I went back and took out the EcommOrderType enumerated member, then re-called the service, yes, the error again went away.

How wacky was that?

Create and consume WCF Service from scratch

Wednesday, September 1st, 2010

Today, I read an article on Codeproject.com by Mike Liu and he gave a very detail illustration on how to create and consume a WCF service from scratch, without using any of those pre-existing WCF templates in VS2010. It was very refreshing and no wonder the article ended up in last month’s new author winner list

These were the steps I went through to create and consume a HelloWorld WCF service following Mike’s instruction:

  1. Selected a Blank solution from VS2010 -> C#/Other Project Types/Visual Studio Solutions
  2. Added a Class library (named HelloWorldService) to the solution (Solution file resided in the root folder and named HelloWorld. When the class lib was created, it automatically created a folder called HelloWorldService)
  3. added a reference to System.ServiceModel.dll to the class lib
  4. Added an Interface class called IHelloWorld.cs to the project and defined ServiceContract and OperationContract, like this:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    namespace Yangsoft.Training.WCF
    { [ServiceContract]
    public interface IHelloWorldService
    {
    [OperationContract]
    String GetMessage(String name); 

    }
    }

     

  5. renamed the class1.cs to HelloWorldService.cs and implemented the interface, like this:class HelloWorldService : IHelloWorldService

    public String GetMessage(String name)
    {

    return “Hello World from ” + name;

    }
    }

  6. Service was created and now it needed to be hosted on a website. To accomplish that, added a new website, named HostDevServer to the HelloWorld solution and made this website use static port: 8080. The website was added as blank website, did not have any string attached and no need to change default web location, File System.
  7. Added a reference to the website project to pick up HelloWorldService class library
  8. Then I opened the web.config; before I added any WCF related stuff, the web.config only had a <system.web> entry. Followed the instruction given in the article, added system.webserver and system.serviceModel sections, now the web.config looks like this:<configuration>
    <system.web>
    <compilation debug=”false” targetFramework=”4.0″ />
    </system.web>
    <system.webServer>
    <modules runAllManagedModulesForAllRequests=”true”></modules>
    </system.webServer>
    <system.serviceModel>
    <behaviors>
    <serviceBehaviors>
    <behavior name=”MyServiceTypeBehaviors”>
    <serviceMetadata httpGetEnabled=”true”/>
    <serviceDebug includeExceptionDetailInFaults=”false”/>
    </behavior>
    </serviceBehaviors>
    </behaviors>
    <services>
    <service name=”Yangsoft.Training.WCF.HelloWorldService” behaviorConfiguration=”MyServiceTypeBehaviors”>
    <endpoint address=”” binding=”wsHttpBinding” contract=”Yangsoft.Training.WCF.IHelloWorldService” ></endpoint>
    <endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange” ></endpoint>
    </service>
    </services>
    </system.serviceModel>
    </configuration>
  9. Now added a .svc file the hardcore way: just added a plain text file called HelloWorldService.svc and added the entry and the only entry to the text file:<%@ ServiceHost Service=”Yangsoft.Training.WCF.HelloWorldService” %>This basically created a website to host the HelloWorlService that a client consume.
  10. Added a Console project, named HelloWorldClient to the solution, no app.config, no other class except the default Program.cs class in the project at this point.
  11. The final piece of major work was to run svcutil.exe to generate the service proxy on this client. This was accomplished all in command line mode:
    • backed out to DOS mode, navigated to the folder where HelloWorldClient console app resided
    • run this command from the folder:“c:\program files\microsoft sdks\windows\v6.0a\bin\svcutil.exe” http://localhost:8080/HostDevServer/HelloWorldService.svc?wsdl after this was run, it generated two files in the HelloWorldClient folder: HelloWorldService.svc and output.config (here I did not follow exactly the instruction given by the Author). Before this was run, I had run the HostDevServer without debuging and checked and made sure the service was created correctly.
    • Returned to the VS2010 solution explorer and go to Project/Show All Files and included the two files created by the svcutil.exe tool in the Console project. Renamed the output.config to app.config and made sure added a reference to the project for System.ServiceModel.
    • Open the Program.cs and added these lines in the Main static method:{
      HelloWorldServiceClient client = new HelloWorldServiceClient();
      Console.WriteLine(client.GetMessage(“Steve Yang”));
      }
    • set the start up project to be the console and hit Ctrl+F5 to run the program in non-debug mode, and the output of the program should be a line saying “Hello World from Steve Yang” or whatevever I programmed in the GetMessage(String name) method in the HelloWorldService.cs in the HelloWorldService class library.
    •  

      In real world of VS2010, I did not have to do all these as there are pre-written WCF templates that I could just drag-and-drop into the solution and automatically populate the web.config and app.config. But I agreed with the author, going through these tedious steps had helped me understand WCF service dearly.