Tuesday, June 30, 2009

Consuming a Web Service with an error in WSDL

In one of my projects I am consuming a third party Web Services, written in I don’t know what. I have WCF Service References to them.

They launces new versions of their services  quit often, so I was fairly sure something was wrong this time. Updating or even deleting and adding references somehow didn’t work right. I could see the service in the browser, after logging on two times (this is normal). Adding or updating  the reference itself also works fine. I’m happy. Started updating all five references, and cleaned up the mess in app.config. Done this many times before. Building.

Error    4    Custom tool error: Failed to generate code for the service reference 'TheService'.  Please check other error and warning messages for details.    D:\temp\ConsoleApplication2\ConsoleApplication2\Service References\TheService\Reference.svcmap    1    1    ConsoleApplication2

What? Expanding all solution files, to investigate the code behind Service Reference/TheService/Reference.svcmap/Reference.cs. Empty!

Running wsdl.exe and svcutil.exe on the downloaded wsdl to investigate more. Finally something to understand: The complexType SomeClass has a property with a blank space in the name attribute. Not allowed. It looked something like this: 

<xs:element name="statusCode " type="foons:StatusCode "/> 




Luckily the vendor was quick to fix this when told. But I really would like Visual Studio to be more robust, either telling me what the problem is when adding a reference to a none valid WSDL or even maybe just remove the whitespace. Like IE does when watching the WSDL file….

Publishing the code samples in Blogspot

I’ve swapped from writing articles inside blogger.com to try out Live Writer. Mainly cause of the hell will copy and pasting in code samples or xml samples. Dave Haynes’s blogged about it here, and I’ll try it out.

Friday, June 26, 2009

WcfService that acts like a WebService

This article is meant as a tutorial for using a logging tool for a WcfServices that looks to the outside world as an old WebService. (Pardon the namespaces, they have been changed to protect the innocent.)

WcfService that acts like a WebService
What I’ve used to do in the past is just add a WCF Service Library to the solution, and make sure binding="basicHttpBinding" is done. This way other platforms and applications could access the service like add web reference that looks something like http://localhost/WebService/WebService.OrderService.svc?wsdl. Why you want to do this? You want to take advantage of what you get in WCF, but still are able to act like a WebService to others that can’t implement WCF Service Reference. Everything else is like standard WCF, [ServiceContract], [OperationContract], [DataContract] and [DataMember] etc.

WcfService that acts like a WebService, but really is a Web Application
Another way of doing this is add a Web Application, strip out all that you don’t need. Like delete Default.aspx*.But instead of adding a new WCF Service, add an ordinary class, and then rename to whatever.svc. And remove all content, and replace it with these few lines:
<%@ ServiceHost Service="Services.OrderService" %>
This service reference should of course map to a class in your solution, probably the business layer. Make sure you add a reference. The business layer would then need a reference to System.Servicemodel to be able to add the needed attributes:

[ServiceBehavior(Namespace = "http://brembo.name/namespace/workorder")]
public class OrderService : IOrderService

[ServiceContract(Name = "OrderService", Namespace = "http://brembo.name/namespace/workorder")]
public interface IOrderService



The web.config would only need these lines (remove everything else):



<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Services.OrderService" behaviorConfiguration="DebuggingBehaviour">
<endpoint address="" binding="basicHttpBinding" bindingNamespace="http://schema.brembo.name/" contract="Services.IOrderService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DebuggingBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>
</configuration>



The Web Application contains by default many no longer needed references. These are the only one needed: System, System.Core, System.Data, System.Runtime.Serialization, System.ServiceModel. Also add your business layer.




If you like to remove the App_Data folder which isn’t needed, unload project, edit project file and remove these lines:



<itemgroup>
<folder include="App_Data\">
</itemgroup>



This should now run as a wcf service, reachable from ordinary WebService clients.

Monday, June 22, 2009

Project References and Copy Local

In our new project we use both NHibernate. The solution consists of the normal layers; data, business, presentation and common.

The data tier has references to NHibernate, and in hibernate.cfg.xml a need for NHibernate.ByteCode.LinFu is configured. The reference to NHibernate is set to copy local, and NHibernate doesn't exist in the GAC. Which otherways could interfere with the copy local. Ok, everything fine so far. Also a need for a reference to NHibernate.ByteCode.LinFu with copy local is needed, since this assembly is needed run-time. Added a reference with copy local, to get this assembly in the runtime folder. I'm not to happy with this reference, but I can leave with it. What I'd really like is NHibernate self to handle this, and get hold of its needed assemblies. But there is a dynamic reference here.

Fine by now, everything ends up in the datalayer\bin\debug folder. Ahh, but then. I add a project reference in the business layer to the data layer. And from the web application there is added a project reference to the business layer. In the Web\bin folder there are missing some dll's after compiling. Everything that NHibernate needs are there (and all other assembly include their needed assemblies), except for NHibernate.ByteCode.LinFu, LinFu.DynamicProxy and hibernate.cfg.xml.

I don't want the client to know about all the different needs my data access has. So linking in files the client itself doesn't need is not a good option for me. Adding references to assembly not needed by the client the same.

So for now I uses post build events on my data project. Copies explicit the needed files to a temporary bin folder.
mkdir "$(SolutionDir)Bin"
xcopy "$(TargetDir)*LinFu*" "$(SolutionDir)Bin" /y
xcopy "$(TargetDir)hibernate.cfg.xml" "$(SolutionDir)Bin" /y

The client copies all files from this directory in the pre build event to the web\bin folder like this:




xcopy "$(SolutionDir)Bin" "$(TargetDir)*.*" /y

This way all the missing files are copied back and forth, ending up where they are needed.

Saturday, June 20, 2009

Toyota Way House

At the Norwegian Developers Conference 2009 I went to the track with Craig Larman, "Toyota Way House".

The Toyota Way 2001 was educational, and explained to me why some of our project had worked and some had not at all... As a developer by heart, I really enjoyed the bit about a manager should be a teacher and technical specialist in the craftmanship. I had to nod my head, wishfully...

http://en.wikipedia.org/wiki/The_Toyota_Way

Monday, June 01, 2009

My customization of blogger.com

Note to myself when I change template, or if others sees the need, this is my few customizations.

Favicon
Just belove the <head> add theese lines:
<link href='http://logica.com/favicon.ico' rel='shortcut icon'/>
<link href='http://logica.com/favicon.ico' rel='icon'/>

To remove the blogspot header, add this line just above the body tag:
#navbar-iframe { display: none !important;}