Importing ASMX Web Service metadata to WCF Endpoint

asmx, metadata, wcf, web-services

Solution

The way to get it to work with an ASMX web service is to specify the MetadataExchangeClientMode

...
MetadataExchangeClient mexClient = 
    new MetadataExchangeClient (new Uri(), MetadataExchangeClientMode.HttpGet);
...

using MetadataExchangeClientMode.HttpGet for your ASMX services and MetadataExchangeClientMode.MetadataExchange for your WCF services.

Problem

I am interested in impersonating well-known Web Services and Wcf Services for integration test purposes. To this end, I would like to capture service metadata, auto-generate service stubs, and host service stubs in a self-hosted environment. Following this article here, I am able to obtain remote Wcf Service metadata and generate contracts. However, I am having some difficulty doing the same for remote Asmx Web Services. I have a set of mickey-mouse solutions for vetting this out. My Asmx solution contains a default "Hello World" web service, found below ``` [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] public class SimpleAsmxService : System.Web.Services.WebService { [WebMethod] public string HelloWorld () { return "Hello World"; } } ``` My Wcf solution contains a default "Hello World" service, also found below ``` [ServiceContract] public interface ISimpleWcfService { [OperationContract] string GetData(int value); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite); } [DataContract] public class CompositeType { [DataMember] public bool BoolValue { get; set; } [DataMember] public string StringValue { get; set; } } public class SimpleWcfService : ISimpleWcfService { public string GetData(int value) { return string.Format("You entered: {0}", value); } public CompositeType GetDataUsingDataContract(CompositeType composite) { if (composite.BoolValue) { composite.StringValue += "Suffix"; } return composite; } } ``` Finally, the little console-that-could looks like ``` class Program { public const string UrlWcf = "http://localhost:8731/Design_Time_Addresses/SimpleWcfService/mex"; public const string UrlAsmx = "http://localhost:1803/SimpleAsmxService.asmx?WSDL"; static void Main(string[] args) { EndpointAddress mexAddress = new EndpointAddress (UrlWcf); MetadataExchangeClient mexClient = new MetadataExchangeClient (mexAddress); mexClient.ResolveMetadataReferences = true; // NOTE: blows up if we use UrlAsmx MetadataSet metaSet = mexClient.GetMetadata (); WsdlImporter importer = new WsdlImporter (metaSet); Collection<ContractDescription> contracts = importer.ImportAllContracts(); } } ``` It seems to me that I should be able to pull Wsdl from a well-known Asmx Web Service and generate contracts [and from contracts to code], but cannot seem to contort the preceding sample to do so. Any help would be much appreciated, Thanks! NOTE: the error generated when invoking `MetadataSet metaSet = mexClient.GetMetadata();` above is a `System.InvalidOperationException` with message of Metadata contains a reference that cannot be resolved : 'http://localhost:1803/SimpleAsmxService.asmx?WSDL' With a `System.InvalidOperationException` inner exception with message of ``` <?xml version="1.0" encoding="utf-16"?> <Fault xmlns="http://www.w3.org/2003/05/soap-envelope"> <Code> <Value>Sender</Value> </Code> <Reason> <Text xml:lang="en"> System.Web.Services.Protocols.SoapException: Unable to handle request without a valid action parameter. Please supply a valid soap action. at System.Web.Services.Protocols.Soap12ServerProtocolHelper.RouteRequest() at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message) at System.Web.Services.Protocols.SoapServerProtocol.Initialize() at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response) at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean&amp; abortProcessing) </Text> </Reason> </Fault> ```

Original source