Category Archives: WCF

Service Reference Failure – Cannot import wsdl:portType

Got an interesting exception whilst adding a service reference to a project, as seen below


Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Could not load file or assembly ‘NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c’ or one of its dependencies. The system cannot find the file specified.

Luckily there’s an easy fix – right mouse click on the reference under the Service References section of the solution and select Configure Service References

ConfigureServiceReference

And as shown, select Reuse types in specified referenced assemblies and check the NLog assembly.

I need to update this post with the whys and wherefores of this change, but it works.

WCF – Basics

I’ve used WCF (and the previous incarnation of web services in .NET) on and off for a while. However once the inital work to set the application up is completed I tend to forget much of what I’ve done to concentrate on the actual application. This is one of the great things with WCF – it just works once set-up.

So this post is going to be written as a quick refresher.

ABC

One of the key things to remember with WCF is the the setting up is pretty much all about the ABC’s

  • A is of Address. In other words what’s the location (or endpoint) of the service.
  • B is of Binding. How do we connect to the endpoint, i.e. what’s the protocol etc.
  • C is of Contract. The application/programming interface to the web service, i.e. what does it do ?

Contracts

Simply put, creating an interface and decorating the interface with [ServiceContract] will mark out an interface as a service contract. Marking the methods that you want to publish with [OperationContract] i.e.

[ServiceContract]
public interface IPlantService
{
   [OperationContract]
   List<Plant> GetPlants();
   // and so on
}

where we’re passing our own complex types back (in the above we have the Plant class) here we mark the class with [DataContract] attribute and each property we wish to publish are marked with [DataMember] as per

[DataContract]
public class Plant
{
   [DataMember]
   public int Id { get; set; }
   [DataMember]
   public string CommonName { get; set; }
   // ... and so on
}

Don’t forget to include the System.ServiceModel assembly and System.Runtime.Serialization.

Hosting a service outside of IIS

Whilst IIS offers a scaleable, consistent and secure architecture for hosting WCF web services, one might prefer to host via a console app or Windows service for example. The following is a simple example of the code needed to get WCF self hosted in a console application.

class Program
{
   static void Main(string[] args)
   {
      ServiceHost serviceHost = new ServiceHost(typeof(PlantService));
      serviceHost.Open();
      Console.WriteLine("Service Running");
      Console.ReadLine();
      serviceHost.Close();
   }
}

Configuring the ABC’s

Configuration of the ABC’s can be accomplished through code or more usually through configuration. I’m not going to dig deep into configuration but instead point to something I’ve only recently been made aware of. Having always edited the app.config by hand.

It’s slightly strange in Visual Studio 2010 how you enable this option but go to Tools | WCF Service Configuration Editor then close it. Now if you right mouse click to get the context menu on the App.config file you’ll see the Edit WCF Configuration option. Now you can configure WCF via this UI.

HTTP could not register URL http://+:8080/ Your process does not have access rights to this namespace

If you’re getting an exception along the lines of “HTTP could not register URL http://+:8080/. Your process does not have access rights to this namespace” whilst writing a WCF web service on Vista or Windows 7 then take a visit to PaulWh’s Tech Blog and download his HttpNamespaceManager.

Just add the url along the lines of http://+8080/ (or whatever port you’re using). Then added group or users (for example BUILTIN\Users and NT AUTHORITY\LOCAL SERVICE) and assign GenericExecute access to them.

This works whilst running within Visual Studio as well as running a standalone EXE.

If you prefer a more hardcore approach then run netsh as admin, either typing

netsh http add urlacl url=http://+:8080/MyService/ user=DOMAIN\user

or you can run netsh (again as admin) and then enter the command

http add urlacl url=http://+:8080/MyService/ user=DOMAIN\user

netsh works like a folder structure, to equally you can type http followed by enter to enter the http section and enter everything after the http section of the command line.

To view the currently set up urlacl’s simple type

netsh http show urlacl

Entity Framework – Dynamic Proxies and WCF

A quick post regarding a simple problem you might find using Entity Framework with WCF. I have a simply little application which uses Entity Framework to access SQL Server and currently this all happens in a little client application.

I decided I wanted to move the DB access into a web service so I could look at writing an iPad or the likes front end to access it. All went well until I got the following exception


An error occurred while receiving the HTTP response to http://localhost:9095/MyService. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.

My web service code looked like the following

public List<Plant> GetPlants()
{
   using (PlantsContext context = new PlantsContext())
   {
       return context.Plants.ToList();
   }
}

The problem is that the return is returning dynamic proxies, of the Plant type, not strictly real Plant types. What we need to do is change the code to add a line to turn off proxy creation

using (PlantsContext context = new PlantsContext())
{
   context.Configuration.ProxyCreationEnabled = false;
   return context.Plants.ToList();
}

And all works.