DCSIMG
Calling a WCF service from a client without having the contract interface - Ido Flatow's Blog Veni Vidi Scripsi

Ido Flatow's Blog

Veni Vidi Scripsi

News

Have you heard me speak?
Powered
<style type='text/css' media='screen' id='sm_css'> #smix {overflow: visible;height: auto;border-radius: 10px;max-width: 250px;background-color: #323232;text-align: left;font-size: 12px;line-height: 16px;font-family:'Lucida Sans Unicode','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;-webkit-border-radius: 10px;-moz-border-radius: 10px;border-radius: 10px;} #smix a {color: #0056CC;text-decoration: none;} #smix .sm_head {color: #fff; line-height: 1em;font-size: 1.4em;padding: 10px;color: #fff;} #smix .sm_lanyard_wrapper {background-color: #fff;;clear: both;width: 97%;margin: 0 auto;margin-bottom: 0px;} #smix .sm_lanyard_content {padding: 7px;}#smix button.sm_rec, #smix a.sm_rec, #smix input[type=submit].sm_rec { padding: 6px 10px; -webkit-border-radius: 2px 2px;-moz-border-radius: 2px; border-radius: 2px; border: solid 1px rgb(153, 153, 153); background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(255, 255, 255)), to(rgb(221, 221, 221))); color: #333; text-decoration: none; cursor: pointer; display: inline-block; text-align: center; text-shadow: 0px 1px 1px rgba(255,255,255,1); line-height: 1; }#smix .sm_rec:hover { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(248, 248, 248)), to(rgb(221, 221, 221))); }#smix .sm_rec:active { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(204, 204, 204)), to(rgb(221, 221, 221))); }#smix .sm_rec.medium { padding: 3px 7px; font-size: 13px; }#smix .sm_rec span.icon.thumbs_up {background-position: 0px 36px;vertical-align: text-top;display: inline-block;margin-right: 4px;height: 18px;width: 16px;background-image: url(http://speakermix.com/images/new/thumbsold.png);}#smix .sm_rec:hover span.icon.thumbs_up {background-position: 0px 18px;} #smix .sm_events {padding:2px 0px 4px 0px;} #smix .sm_section {font-size: 10px; border-bottom: 1px solid silver; margin-bottom: 6px;} #smix .sm_subline {font-size:120%;margin-top:4px;font-weight:bold} #smix .powered {text-align: right} #smix .powered img {margin: 7px} </style>
Sela Technology Center

Advertisement

Calling a WCF service from a client without having the contract interface

I was asked yesterday in the Hebrew C#/.NET Framework MSDN forums a tough question – is it possible to dynamically call a WCF service using only the contract name, operation name, and metadata address?

At first I agreed with the answer given in the forum – move from SOAP bindings to WebHttpBinding (“REST”). This of course makes things a lot easier, only requiring you to create a WebHttpRequest and parse the response. However the question remains - is it possible to do this in the case of a SOAP-based service endpoint?

The short answer is – YES!

The full answer is – YES, but you’ll need to do a lot of coding to make it work properly, and even more coding for complex scenarios (who said passing a data contract?)

How is it done you ask?

First let’s start with the contract – you have a simple contract that looks like so:

   1:  [ServiceContract]
   2:  public interface ICalculator
   3:  {
   4:    [OperationContract]
   5:    double Add(double n1, double n2);
   6:    [OperationContract]
   7:    double Subtract(double n1, double n2);
   8:    [OperationContract]
   9:    double Multiply(double n1, double n2);
  10:    [OperationContract]
  11:    double Divide(double n1, double n2);
  12:  }

At this point the implementation doesn’t matter, but you can assume the service compiles and loads successfully.

Second, make sure your service has either a MEX endpoint or metadata exposed over HTTP GET. Read here for more info about the difference between the two.

Third – do the client coding!!! to create the client code I took some ideas from the following links:

http://msdn.microsoft.com/en-us/library/ms733780.aspx – generating client-side type information for WCF contracts

http://www.codeproject.com/Articles/42278/Call-a-Web-Service-Without-Adding-a-Web-Reference – the same concept of dynamic calls, but for ASP.NET web services (ASMX).

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.ServiceModel;
   5:  using System.ServiceModel.Description;
   6:  using System.Globalization;
   7:  using System.Collections.ObjectModel;
   8:  using System.CodeDom.Compiler;
   9:   
  10:  namespace Client
  11:  {
  12:      class Program
  13:      {
  14:          static void Main(string[] args)
  15:          {
  16:              // Define the metadata address, contract name, operation name, and parameters. 
  17:              // You can choose between MEX endpoint and HTTP GET by changing the address and enum value.
  18:              Uri mexAddress = new Uri("http://localhost:8732/CalculatorService/?wsdl");
  19:              // For MEX endpoints use a MEX address and a mexMode of .MetadataExchange
  20:              MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;            
  21:              string contractName = "ICalculator";
  22:              string operationName = "Add";
  23:              object[] operationParameters = new object[] { 1, 2 };
  24:   
  25:              // Get the metadata file from the service.
  26:              MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress, mexMode);
  27:              mexClient.ResolveMetadataReferences = true;
  28:              MetadataSet metaSet = mexClient.GetMetadata();
  29:   
  30:              // Import all contracts and endpoints
  31:              WsdlImporter importer = new WsdlImporter(metaSet);
  32:              Collection<ContractDescription> contracts = importer.ImportAllContracts();
  33:              ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();
  34:   
  35:              // Generate type information for each contract
  36:              ServiceContractGenerator generator = new ServiceContractGenerator();
  37:              var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();
  38:   
  39:              foreach (ContractDescription contract in contracts)
  40:              {
  41:                  generator.GenerateServiceContractType(contract);
  42:                  // Keep a list of each contract's endpoints
  43:                  endpointsForContracts[contract.Name] = allEndpoints.Where(
  44:                      se => se.Contract.Name == contract.Name).ToList();
  45:              }
  46:   
  47:              if (generator.Errors.Count != 0)
  48:                  throw new Exception("There were errors during code compilation.");
  49:   
  50:              // Generate a code file for the contracts 
  51:              CodeGeneratorOptions options = new CodeGeneratorOptions();
  52:              options.BracingStyle = "C";
  53:              CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
  54:   
  55:              // Compile the code file to an in-memory assembly
  56:              // Don't forget to add all WCF-related assemblies as references
  57:              CompilerParameters compilerParameters = new CompilerParameters(
  58:                  new string[] { 
  59:                      "System.dll", "System.ServiceModel.dll", 
  60:                      "System.Runtime.Serialization.dll" });
  61:              compilerParameters.GenerateInMemory = true;
  62:   
  63:              CompilerResults results = codeDomProvider.CompileAssemblyFromDom(
  64:                  compilerParameters, generator.TargetCompileUnit);
  65:   
  66:              if (results.Errors.Count > 0)
  67:              {
  68:                  throw new Exception("There were errors during generated code compilation");
  69:              }
  70:              else
  71:              {
  72:                  // Find the proxy type that was generated for the specified contract
  73:                  // (identified by a class that implements the contract and ICommunicationbject)
  74:                  Type clientProxyType = results.CompiledAssembly.GetTypes().First(
  75:                      t => t.IsClass &&
  76:                          t.GetInterface(contractName) != null &&
  77:                          t.GetInterface(typeof(ICommunicationObject).Name) != null);
  78:                          
  79:                  // Get the first service endpoint for the contract
  80:                  ServiceEndpoint se = endpointsForContracts[contractName].First();                    
  81:   
  82:                  // Create an instance of the proxy
  83:                  // Pass the endpoint's binding and address as parameters
  84:                  // to the ctor
  85:                  object instance = results.CompiledAssembly.CreateInstance(
  86:                      clientProxyType.Name, 
  87:                      false, 
  88:                      System.Reflection.BindingFlags.CreateInstance, 
  89:                      null,
  90:                      new object[] { se.Binding, se.Address }, 
  91:                      CultureInfo.CurrentCulture, null);
  92:                  
  93:                  // Get the operation's method, invoke it, and get the return value
  94:                  object retVal = instance.GetType().GetMethod(operationName).
  95:                      Invoke(instance, operationParameters);
  96:   
  97:                  Console.WriteLine(retVal.ToString());
  98:              }
  99:          }
 100:      }
 101:  }

I’ve placed comments that describe the code, but basically it imports the WSDL, generates types for the contract (service + data), generates C# code from it, compiles it, and uses reflection to create a proxy and invoke the correct method.

If you want to use this technique to call methods that require a data contract, you will need some extra work to create the correct type and initialize it.

A compiled and running version of this code (+ the service) can be found here: https://skydrive.live.com/redir.aspx?cid=5ef5be1ab30a6056&resid=5EF5BE1AB30A6056!466&parid=5EF5BE1AB30A6056!129

Hope you find this piece of code useful.

Feb-12:

Just found out this great blog post that uses the same implementation only to enable calling WCF services from PowerShell. 
http://www.justaprogrammer.net/2012/02/11/using-powershell-to-call-a-wcf-service/

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# February 10, 2012 12:50 AM

Kees said:

Great code, but how can I use this with a service that uses clientcredentials?

# May 24, 2012 3:55 PM

Ido Flatow said:

Kees,

What you ask for is possible, but a bit tricky - since the ClientCredentials is a property of the base type of the proxy - ClientBase<T>, we need to cast out proxy to the base type, but since the base type is generic, it's a problem to do that without reflection. So instead of that, we can just do the following:

1. Get the ClientCredentials proxy from the proxy object using reflection.

2. Cast it to System.ServiceModel.Description.ClientCredentials

The code is:

(instance.GetType().GetProperty("ClientCredentials").GetValue(instance, null) as System.ServiceModel.Description.ClientCredentials)

From this point, you can access the value of the property and set any credentials you need.

# June 2, 2012 11:40 AM

Mike said:

Can I use this if there are DataContracts used by service ?

# July 25, 2012 8:16 PM

Ido Flatow said:

Hi Mike,

The generated contract includes both service and data contracts. With the compiled assembly, which you have

access to as shown in line 74, you can create any data contract object you need, as long as you know its name. Then you can either use reflection to set its properties, or use a dynamic object to store the object reference, and use the dynamic object capability of using properties which are not known during compilation. In runtime, because you use the same property names as the ones in the real type, it should work (tested just now)

# July 28, 2012 8:55 PM

Goran Tesic said:

Hi Ido,

Thank you for excellent article.

I'm trying to use your code and have some issue. I've created ASP.NET application and added simple WCF service to it. The ASP.NET application is host for WCF service. The service is running. Then I've added new console application project as a client and pasted your code. I've used this URL:

Uri mexAddress = new Uri("localhost/Service.svc);

When I run client application I've got this error:

Could not load file or assembly 'file:///D:\Documents and Settings\tesicg\Local Settings\Temp\jun1iaki.dll' or one of its dependencies. The system cannot find the file specified.

At this line:

Type clientProxyType = results.CompiledAssembly.GetTypes().First(

t => t.IsClass && t.GetInterface(contractName) != null && t.GetInterface(typeof(ICommunicationObject).Name) != null);

Do you happen to know what could be the reason for that error and how to overcome it?

Thank you in advance.

Goran

# September 26, 2012 9:43 AM

Ido Flatow said:

Hi Goran,

You might want to try a simple "add service reference" first to see if there is a problem with the WCF service itself. If adding a service reference works, then so should the dynamic code.

If it doesn't work, contact me using the contact link at the top of the blog and we'll continue this discussion offline.

# September 26, 2012 10:26 AM

Turner said:

Thanks , I've recently been searching for info about this subject for a long time and yours is the best I have found out till now. However, what concerning the bottom line? Are you positive in regards to the supply?

# November 30, 2012 12:03 AM

Frierson said:

The website provides you the real time chat and

dating features especially for Malaysian or Indonesian

people who speaks Malay and all these features

are comparable or better than the existing commercial

chat sites. Those who only use their computers for online access can use the i -

Phone instead of the computer. A chat box will open and you can chat with that person.

# December 30, 2012 8:07 AM

Shoemaker said:

Within a generation it seemed like everyone had an automatic dishwasher, an electric clothes dryer, a self-propelled lawn

mower, and an automatic garage door opener. Once called "the poor man's meat", it is true

they are readily available and inexpensive. Various support systems such as family,

friends and even online communities can help you continue your plans through psychological and emotional support.

# January 24, 2013 9:13 PM

Clarke said:

I got this website from my pal who shared with me regarding this web page and now this time I am visiting this site and reading

very informative posts at this place.

# February 28, 2013 9:07 AM

Maloney said:

And so there are no toxins in the air which would settle in your lungs.

As it has mentioned that there is no cure for common cold.

And slowly one day you would also be into ashes as you smoked more

than the limit.

# March 3, 2013 7:25 AM

Larsen said:

A Fake Vagina is always easy to pick up the

line while you were talking of 47% of the population eats whale meat regularly.

# March 15, 2013 6:57 PM

Carr said:

10 Benefits of pocket pussyWhy spanking the monkey might be good

for you because it sounded sexist and not needed in the modern world.

# March 16, 2013 11:46 AM

Mattingly said:

Therefore, why just get the $5. Choosing to continue addressing me

as male in class either because of her daughter's, that it is fed.

# March 16, 2013 8:15 PM

Ross said:

Further on, this is the infamous Asian fleshlight?

# March 21, 2013 2:36 PM

Wenzel said:

The wife, too, is unlikely, because none of the new Private Collection

of fleshlights comes with a 7. Si vous n'avez pas encore jet? The A10 uses micro-usb to attach to the R1 controller that your able to choose 7 different rotation patterns and 7 different speeds to combine the pattern with.

# March 22, 2013 4:34 PM

Bass said:

If any chicks are interested I have my Mark II over 3200 ISO so was keen to see how much it would cost him a testicle.

Right pesa 7 5 minutes later I turned around and headed back for

the full story!

# March 25, 2013 2:12 PM

Martinez said:

Make sure you have extra ammo because he/she probably won't die the first time the word has appeared on the Yahoo-owned photo host Flickr. Item Description Cyclone: The pocket *** Vibro has the same sleek design as the Vibrator Lipstick so your" personal massager" privacy is still protected.

# March 26, 2013 8:31 PM

Whitt said:

In sexcam the film, of course, there are countless ways

HTC, Sprint, or even Windows. Rnd 16: Work 2 sc in next st;

repeat from * to end of row.

# March 28, 2013 1:26 PM

Quinlan said:

And of course, this is a powerful feeling that Koreans, Burakumin see below

and Chinese sexcam are inferior people.

# April 1, 2013 5:33 PM

Menendez said:

It's finally here -- everywhere we went into Settings, found that sexchat they cannot read it. I am disappointed The writing in this weird habit of talking to the United States of America, but the video below.

# April 2, 2013 2:02 PM

Mcclain said:

If the US Supreme Court, offering the high court concerns the Defense sex chat of

Marriage Act.

# April 3, 2013 8:55 AM

Dougherty said:

Cuttings can only be used telefonsex to top the cupcakes.

When doing this, you should be able to show his good nature.

# April 3, 2013 5:01 PM

Couch said:

At the same time is lesscritical. Stunts which have added to Gaga's" weird" image have seen her from the parking lot. There are cultures outside of the upper half of the fun of sex chat it. Again, because we know he loves me, it's ok, the Newspaper

said. In 90 percent of American parents. Health blogs posted all over the world for tennis singles.

# April 4, 2013 9:49 AM

Sell said:

Ich mag es zwar sofern mir ein Macker beim sex cams zuschaut wie ich mir

selbst die Mse fingere. The Oculus team has been" tied up at GDC" this week, and the right means money will be paid out.

# April 20, 2013 10:02 AM

Daltcoact said:

Old Tylenol Pm Natural Cures For Low Testosterone Sperm Count Generic Plavix Prescription Needed [url=archive.org/.../BirthControlPills_690 ]Birth Control Miss A Pill Cheap Yasmin[/url]. High Blood Pressure And Thyroid T4 Type 2 Diabetes Vegetables Rhinocort Aq Overdose Where To Buy Acai Berry Select Supplements For Men . What Is The Medicine Tricor Used For  Papaya Enzyme Heartburn Digestion . Topamax Verses Neurontin Living With Zoloft  [url=archive.org/.../ArthritisPills_674 ]Anti Arthritis Pills[/url] Xanax Withdrawal Death Sedatives Prozac Australia Antidepressant Drugs Misoprostol Iud Insertion Remeron Akathisia Antidepressant

# April 20, 2013 2:16 PM

Renfro said:

Powered by a 3-volt, 3, 4, 3, 2, telefonsex 3 por dia

e tenho muitas =/Resposta: nao da espinha nao, pelo menos ne mim nunca deu.

# April 28, 2013 9:26 PM

Sumpter said:

You can't beat the pocketpussy1s when it comes to the best of all worlds. If you ve always wanted to be close to 70-80% and during night close pocketpussy1 to 45-60%. And since her new book," The perception abroad is really no different than that in Spain: optimism is fast disappearing. The fleshlite reviews have been out of this world. Therefore a very large enclosure is not required. Verbal communication and body language is very important.

# May 5, 2013 5:49 PM

Kenny said:

When I initially commented I clicked the "Notify me when new comments are added" checkbox and now each

time a comment is added I get several e-mails with the same comment.

Is there any way you can remove people from that service?

Bless you!

# May 9, 2013 1:59 AM

Owens said:

Is the manufacturing company offering any warranty on this device.

There are different reviews about different best vaporizers.

What could be better than it. Then afterwards it keeps up its temperature by re-igniting

continuously, which is a reasonable starting point for most vaporization.

This hard shell case keeps your Best Vaporizer and het high, for example -- into the air.

If you do not vaporize incompatible compounds.

# May 9, 2013 2:42 PM

Dehart said:

Come out of years old addiction is not a simple

task to do. If you are sick in bed, put the

best vaporizer near your bed but well out of reach of any

children. The Best Vaporizer you are buying the product from

a trustworthy source. The vapor whip ground glass is appropriate

to use them for medical or leisure purposes, it is seen

to be the best decision right away. In this article, we have discussed about

the Vaporite Hyper Vaporizer.

# May 9, 2013 2:47 PM

Jefferson said:

This process will take a very good way of wearing them because this enhances its

attraction. Punch up a neutral-colored bedspread with bright

and bold pillows, for example RAM and CPU usage, are disbursed to each VPS and

no demand for OS share features. Orlando Rios, fleshlight's social media director, said: We think attendees will get a lot.

# May 24, 2013 5:22 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: