ASMX Hello World as it REALLY ought to be

I did a presentation on ASMX 2.0 in the Atlanta office that showed off designing services using interfaces.  I boned it up.  In fact, I even boned up an earlier blog entry using the same demo with the same error in it

Brandon Ording attended the session, then called me on the demo I did in the event as well as what I put on my blog.  He pointed out that the service still reports having tempuri.org as the default namespace, and there are several extra bindings in there.  Yep... pull up the WSDL, and that isn't what I intended at all.

I started tinkering to see if I could create the expected WSDL by hand.  I rolled the WSDL, ran wsdl.exe with the /serverInterface switch, then implemented the interface that was generated.  Still got the error about tempuri.org.  Man!  What am I doing wrong?

I searched the web for "serverInterface", and turned up this example.  There it was staring me in the face, and my earlier blog example will turn up some bizarre results. 

If you notice, I put the WebServiceAttribute on the interface in my earlier post.  This has a very bizarre side effect of creating a few extra and unexpected bindings.  Worse, you will get an error about the service using tempuri.org as the default namespace, even though it was specified in the WebServiceAttribute.  Sure enough, open the WSDL and you will see tempuri.org in there.

That led to some more digging to try to understand what the WebServiceBindingAttribute is really doing and meant for.  If you are interested in more, see Yasser's book that shows how the attribute can be used to implement multiple interfaces.

So, to rectify... here is ASMX Hello World as it REALLY ought to be, with the WebService attribute defining the namespace on the class and not applied to the interface.  Note that it still emits two bindings, MyServiceBinding and MyServiceBinding1.  MyServiceBinding1 is the SOAP 1.2 binding.  A key difference between these bindings is that the WS-I conformance claims are only emitted for the SOAP 1.1 binding.  Not emitting conformance claims for the SOAP 1.2 binding makes sense since the WS-I Basic Profile 1.1 only covers SOAP 1.1 and not SOAP 1.2.

 using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.Xml.Serialization;

[WebServiceBinding(  
    Name="MyServiceBinding", 
    Namespace="urn:foo:bar", 
    ConformsTo=WsiProfiles.BasicProfile1_1, 
    EmitConformanceClaims=true)]
public interface IService
{
    [WebMethod]
    HelloResponse HelloWorld(HelloRequest request);
}

[WebService(Namespace = "urn:foo:bar", Name="My Soap Service")]
[SoapDocumentService(ParameterStyle = SoapParameterStyle.Bare)]
public class ServiceBinding : IService
{    
    public HelloResponse HelloWorld(HelloRequest request)
    {
        HelloResponse response = new HelloResponse();
        response.Message = "Hello";
        return response;
    }   
}

[XmlType(TypeName = "HelloResponse", Namespace = "urn:foo:bar")]
public class HelloResponse
{    
    private string _message;

    [XmlElement(ElementName = "ResponseMessage")]
    public string Message
    {
        get { return _message; }
        set { _message = value; }
    }
    
}

[XmlType(TypeName = "HelloRequest", Namespace = "urn:foo:bar")]
public class HelloRequest
{
}