Dynamic Programming with WCF



Update: Please check out the post on memory footprint and dynamic proxy (http://blogs.msdn.com/vipulmodi/archive/2008/10/16/dynamic-proxy-and-memory-footprint.aspx


—–


Ever wonder what it would like to go from WSDL to code at runtime? Check out my WCF Dynamic Proxy tool that I posted on the wcf.nefx3.com community site. The WCF Dynamic Proxy downloads the WSDL, generate the code, compile the code and then allow you to invoke the web service operations using reflection, all at runtime. Here is the readme from the tool: http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=netfxsamples&DownloadId=3939


The DynamicProxy allows you to create the dynamic WCF client at runtime by specifying the WSDL URI of the service. The DynamicProxy does not depend on the precompiled proxy or configuration. The DynamicProxy uses the MetadataResolver to download the metadata from the service and WsdlImporter to create the contract and binding at runtime. The compiled dynamic proxy can be used to invoke the operations on the service using reflection.


The example shows how you can the dynamic proxy to invoke operations that use simple types and complex types. The flow of usage is as following.


1. Create the ProxyFactory specifying the WSDL URI of the service.


    DynamicProxyFactory factory = new DynamicProxyFactory(“http://localhost:8080/WcfSamples/DynamicProxy?wsdl“);


2. Browse the endpoints, metadata, contracts etc.
    factory.Endpoints
    factory.Metadata
    factory.Contracts
    factory.Bindings


3. Create DynamicProxy to an endpoint by specifying either the endpoint or
   contract name.
    DynamicProxy proxy = factory.CreateProxy(“ISimpleCalculator”);


    OR


    DynamicProxy proxy = factory.CreateProxy(endpoint);
   
  
4. Invoke operations on the DynamicProxy
    dobule result = (dobule)proxy.CallMethod(“Add”, 1d ,2d);


5. Close the DynamicProxy
    proxy.Close();


Comments (64)

  1. Pascal says:

    Hi,

    We had to face similar problematics, the result is two libraries.

    The first one uses only .NET 2.0 and offers similar programmatic experience for Asmx, Remoting and Wse 3.0. You can have a look at http://www.codeplex.com/ProxyFactory.

    The second uses WCF and it introduces the concept of leveraging a service metadata in order to retrieve at runtime its endpoint configuration therefore avoiding duplicating the configuration information on both service and all its clients. It is also leveraging ChannelFactory<T> for strongly typed proxy generation.

    Article, video and sample code are available at this url : http://netfxfactory.org/blogs/papers/archive/2007/01/24/An-effective-way-to-access-wcf-services.aspx

    We would be interested by your feedback.

  2. DJ Yang says:

    Is there sample for "net.tcp://www.codeplex.com/ProxyFactory."?

    Thanks a lot.

  3. Pascal says:

    A remonting sample (tcp://localhost:9000/AccountManager.rem) is provided in the getting started of the ProxyFactory project.

    And the SmartChannelFactory project based on WCF technology supports, of course, the NetTcpBinding.

  4. DashHunter says:

    I tried to implement the same factory concept in my apps. , in which i want to dynamically invoke different third party webservices and is giving issues regarding the contracts. I will not be able to implement the contract info into these third aprty webservices, but i want to invoke them on fly.

    How can i go about resolving it…

    tips welcome..

  5. JeffAtAon says:

    When I try to read WSDL using the dynamic proxy class in this blog, for certain web services I get the an error message similar to the following:

    "Cannot import wsdl:bindingrnDetail: The required WSDL extension element ‘binding’ from namespace ‘http://schemas.xmlsoap.org/wsdl/http/‘ was not handled.rnXPath to Error Source: //wsdl:definitions[@targetNamespace=’http://someurl.com‘]/wsdl:binding[@name=’StockQuotesHttpGet’]"

    I’ve noticed that the error always occurs on web services with HttpPost and HttpGet bindings.  I can read these web services successfully with webservicestudio, so I know the WSDL is valid.  Could this be a WCF/WSE limitation?  Any ideas on how to resolve it?

  6. Gustavo says:

    Will it work with any kind of binding, including netMsmqBinding (with metadata through WS HTTP binding)?

  7. Rama says:

    Hi Vipul

    Can I use DynamicProxy with NetDataContractSerializer. I am trying to refer the NetDataContractSerializer (Aaron Skonnard’s implementation) with Dynamic Proxy, and I am getting the dynamicproxy dll not found error while invoking the service. Any help is highly appreciated

    Rama

  8. shikha says:

    How to do Exception handling with Dynamic proxy

  9. Marco says:

    Hi,

    i’m testing this component but i have a problem. For certain wsdl document i receive this exception

    "THERE WAS AN ERROR IN IMPORTING THE METADATA"

    What does it mean?

  10. shilpa says:

    Hi,

    i’m testing this component but i have a problem. For certain wsdl document i receive this exception

    "THERE WAS AN ERROR IN IMPORTING THE METADATA"

    What does it mean?

  11. Jack says:

    i just want to get on at school

  12. James says:

    Thanks for the excellent work.  I was able to incorporate this into a client console application in my environment, which works fine, but when using a WinForms client, the call to serviceFinder.Probe() always results in a timeout.  I suspect this may be related to SynchronizationContext, but have been unable to overcome the issue.  Any suggestions would be appreciated.

  13. vipulm says:

    Thanks for using the sample and thanks for the comments. Let me try to answer some them here.

    1. Can I use Dynamic Proxy with other bindings?

      Yes you can.

    2. I get an error while creating the factory.

      Run SVCUTIL on the URL you are trying to create the proxy for. If SVCUTIL gives an error the dynamic proxy will. Try to debug the issue with SVCUTIL.

    3. What about downloading the metadata through MEX endpoint instead of ?wsdl.

      Yes, you can modify the sample to download metadata using System.ServiceModel.Description.MetadataExchangeClient.

    4. What about complex types in my service contact, how do I use them?

       If you already have the service contract and types pregenerated, you can simply create a channel factory using known service contract and binding and address given to you by the dynamic proxy factory.

       If you do not have the service contract before hand, you are left with using Reflection. The sample provide an example of Complex type (DynamicComplexNumber.cs).

  14. A while back I published a post about dynamic programming with WCF using the dynamic proxy library that

  15. Rahman says:

    First, i must thank u for this great work!!!

    I have a question: How can i call my service’s Methods asynchronously? i want to use asynchronous operations by using this Library(Dynamic Proxy) but i haven’t found any way.

    Could u help me ….

    thanks

    Rahman

  16. Hi, I Solved My Problem!!

    I changed the Library’s Code and by that,   asynchronous Operations generate Dynamically!

    i will published the changed library in the CodeProject Site very Soon.

    I Hope it will be useful …

    R. Khanipour

  17. rick watson says:

    Good morning, I have tested your client with my application and have gotten data back from the database. the issue… my configuration files from app.config are not being read. the one which is complaining is maxreceivedmessagesize. unfortunately it is set to default of 65536. How can I get more data than this on a call to the database. thank you for any assistance. rick. You may respond also to rwatson@ogleveeltd.com

  18. Vikas Jain says:

    Hi Vipul,

    How can I get my Properties in a Complex Type reconstructed in the Proxy code. Using the current code, the property names are replaced by their corresponding private variables in the proxy code.

    Thanks,

    Vikas

  19. ranger63 says:

    I have a similar issue. I have xyz WCF Service that inherits from xyzBase. xyzBase has a property that I want to access. When I create a proxy class no metadata is generated for the property that is defined in the base class. In other words, when I try:  

    PropertyInfo fi = webService.GetType().GetProperty("ServiceHeaderValue");

    it cannot find the ServiceHeaderValue propery. When I use traditional ASP.NET service this works fine. I can see using Lutz Reflector that the property is being exposed .. it just doesn;t seem to make it into the proxy class genertaed by svcutil.exe.

    Any ideas would be greatly appreciated.

  20. Hi Vipul

    Is it possible to pass a cookie to the dynamic proxy before calling the invokeMember function.  I am having trouble accessing an endpoint that needs to have authentication (We are implementing SSO).  Many thanks for your help.

    Kind Regards

  21. Kris says:

    Hi Vipul,

    I was able to extract the the input parameters to "MyMethod" function by doing the following:

    DynamicProxy _dp = _dpf.CreateProxy(endpoint);

    Type proxyType = _dp.ProxyType;

    MethodInfo method = proxyType.GetMethod("MyMethod");

    ParameterInfo[] inputParameters = method.GetParameters();

    My output parameter is complex structure represented in the WSDL by the xml bellow. I am not sure how I can retrieve the type and name of each output parameter within the complex one!

    <s:complexType name="ProcessStats">

     <s:sequence>

      <s:element minOccurs="1" maxOccurs="1" name="accessDenied" type="s:boolean"/>

      <s:element minOccurs="1" maxOccurs="1" name="isRunning" type="s:boolean"/>

      <s:element minOccurs="1" maxOccurs="1" name="processID" type="s:int"/>

      <s:element minOccurs="0" maxOccurs="1" name="processName" type="s:string"/>

      <s:element minOccurs="1" maxOccurs="1" name="totalRunTime" type="s:double"/>

      <s:element minOccurs="0" maxOccurs="1" name="errorDescription" type="s:string"/>

     </s:sequence>

    </s:complexType>

    The same is true for complex input parameters!  Do you know if there is a clear way to do this?

    Thank you very much.

  22. Pradyot Ranjan says:

    Hi Vipul;

    Thanks For your Post. can you please help me to solve one issue. I am using dynamicproxy dll in my client application, when I run my client application and try to invoke some services(WCF) its showing error saying that "The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element."

    I google for this error and get a fix,When we add a service in our client Application it created binding configuration there we need to change MaxReceivedMessageSize.

    my question is how we change MaxReceivedMessageSize value in DynamicProxy  

  23. Srinivas says:

    WSHttpBinding b = new WSHttpBinding(SecurityMode.None);

    b.MessageEncoding = WSMessageEncoding.Mtom;

               b.TransferMode = TransferMode.Streamed;

               b.ReaderQuotas.MaxStringContentLength = 99999;

    still i get error when i pass large data.

    Help needed

  24. Harry Pooni says:

    Can you provide example on how to create an instance of a custom DataMember class and use it within the Proxy?

  25. Boris says:

    Works great, but I need to customize binding because my service host is Java based.

    I tried to change factory.Bindings and add extra behaviors to factory.Endpoints, but they don’t seem to be changing anything in the Proxy?

  26. Jin Khai (sovietmah@gmail.com) says:

    How to connect to WCF web services and by passing complex data object?

  27. vikas mestry says:

    Hi,

    I tried using the dynamicproxy in my code, i am currently facing an issue, when i try to pass a DataContract object i am getting Missing Method Exception thrown from the CallMethod function, tried googling but couldn’t find a solution to the same, it seems that the invokemember of reflection class is throwing the error, but i couldn’t get a concrete solution.

    Any helps appretiated

  28. Kristian Georgiev says:

    Hi Vipul,

    I have similar question to others concerning setting MaxReceivedMessageSize value in DynamicProxy.  I tried different things but they don’t seem to make any difference.  Your help is appreciated.  If you can give us a code snippet that will be great.

  29. krisgg says:

    I used to create a dynamic proxy by specifying the contractName and that worked fine for a while until I encountered some size limitations and I had to change the http bindings in the Endpoint.  Not knowing that I can’t change the Endpoint once it has been open by the client I tried multiple things to get MaxReceivedMessageSize and other settings changed.  So it dawned on me that I need to change the Endpoint first and then create the dynamic proxy with the correct settings.  So here are a few lines of code that might help you if you encounter this issue (of course you can change other setting at will):

    // create the proxy library

    DynamicProxyFactory dpf = new DynamicProxyFactory("your wsdl url here");

    // retrieve the appropriate endpoint and set binding values

    ServiceEndpoint serviceEndpoint = dpf.GetEndpoint("your web service contract name here");

    ((BasicHttpBinding)(serviceEndpoint.Binding)).MaxBufferSize = int.MaxValue;

    ((BasicHttpBinding)(serviceEndpoint.Binding)).MaxReceivedMessageSize = int.MaxValue;

    ((BasicHttpBinding)(serviceEndpoint.Binding)).ReaderQuotas.MaxArrayLength = int.MaxValue;

    ((BasicHttpBinding)(serviceEndpoint.Binding)).ReaderQuotas.MaxBytesPerRead = int.MaxValue;

    ((BasicHttpBinding)(serviceEndpoint.Binding)).ReaderQuotas.MaxDepth = int.MaxValue;

    ((BasicHttpBinding)(serviceEndpoint.Binding)).ReaderQuotas.MaxNameTableCharCount = int.MaxValue;

    ((BasicHttpBinding)(serviceEndpoint.Binding)).ReaderQuotas.MaxStringContentLength = int.MaxValue;

    // We are ready to create the dynamic proxy

    DynamicProxy dp = dpf.CreateProxy(serviceEndpoint);

    // If you need to change the proxy timeout settings you do it after you initialize it (like this)

    // set the Timeout Property for this web service call

    IClientChannel contextChannelProperty = (IClientChannel)dp.GetProperty("InnerChannel");

    contextChannelProperty.OperationTimeout = new TimeSpan(0, hours, minutes, seconds, 0);

    // now we can call our method to execute the web service

    object temp_output = dp.CallMethod("the name of your web service function", inputParams);

    I hope this code helps.

    Kris

  30. vikas mestry says:

    I have made a simple addition to the Dynamic Proxy project, added a new class DynamicProxyClass which inherits from Dynamic Object, modified the GetType function in the class to

    public static Type GetType(Assembly assembly, string TypeName)

           {

               return assembly.GetType(TypeName, true, true);

           }

    sending the type from outside rather than hard-coding it.

    so for creating an object doing something like this

    DynamicProxyClass requestProxy = new DynamicProxyClass(factory.ProxyAssembly, CLASS.GetType().ToString());

    more info on this @ http://dvij.blogspot.com/2010/03/implementing-dynamic-proxy-in-wcf.html

  31. Howard Davis says:

    How do you build  the WSDL string("http://localhost:8080/WcfSamples/DynamicProxy?wsdl&quot;);

    what does WcfSamples signify, Can I choose any name?   Then do I need to specify "DynamicProx?wsdl"?

  32. George says:

    @vikas make sure you call your method using the correct params (count and type).

  33. naresh says:

    hi, vipul. i am using your tool. it is very good. But i am in very big problem that is "how can i pass UserName  and password by using your tool. i am using wsHttpBinding". please help me.

    my email ID is "naresh_soni44@yahoo.com"

  34. Jenks says:

    Hi Vipul,

    how to pass ref and out parameters to/from WCF using Dynamic Proxy Class Library

  35. sideburn42 says:

    This daynamic proxy code is awesome!  I've modified the DownloadMetadata function like this:

    EndpointAddress epr = new EndpointAddress(this.wsdlUri);

    MetadataExchangeClient mexC = new MetadataExchangeClient(new Uri(this.wsdlUri), MetadataExchangeClientMode.MetadataExchange);

    MetadataSet metaDataset = mexC.GetMetadata();

    this.metadataCollection = new Collection<MetadataSection>();

    foreach (MetadataSection mds in metaDataset.MetadataSections)

    {

        this.metadataCollection.Add(mds);

    }

    to allow downloading the metadata over a NetTCP MEX endpoint.

    What I'm trying to do now is allow generating a proxy with a callback fuction (to support a tcp duplex channel.)  The code currently throws a DynamicProxyException("The constructor matching the specified parameter types is not found.")  Ideally the code would be generated with a callback event that could be handled in the client application.  

    Please let me know if anyone has already done this, or has a good approach to look into.

  36. Christian Findlay says:

    This is an interesting idea. Is there a Silverlight version? You can achieve part of this functionality in Silverlight with a sample that I created here (obviously not as comprehensive as this solution though)

    christianfindlay.blogspot.com/…/dynamic-wcf-services-silverlight.html

  37. Csaba says:

    Thanks for that great work Vipul!

    How can I pass UserName  and password by using your tool?

  38. Csaba says:

    I solved the credentials problem.

    DiscoveryClientProtocol disco = new DiscoveryClientProtocol();

    disco.UseDefaultCredentials = false;

    disco.Credentials = new NetworkCredentials("userName", "password");

  39. How to begin! says:

    Hey I am not able to build you project! How do i start off :/

  40. Cool Stuff says:

    This stuff is cool… but i am not able to run it yet. When i try to expose methods in my Service it si showing error method name not found.

    I am working on WCF Workflow service which is hosted in IIs. Do your code support xamlx?

  41. Dakshina says:

    Hi Vipul,

    Is there a way to invoke methods on a asmx service dynamically using your library

  42. ardi says:

    have you try it on WCF 4 Workflow Services ? its got error Method not found, I'm sure the method exist.

  43. Peter says:

    Great little tool. I would like to be able to use it with a service over SSL. Where in your code should I load the client X509 cert? I tried disco.ClientCertificates.Add(cert); but that didn't work.

  44. Vineeth says:

    How to specify the collection Type I need Collection type as List not as array

  45. Harshil Gandhi says:

    Hello sir,Nice post.i am novice in WCF programming.when i call my service using Dynamic Proxy class,it gives me an error on call method."Method Not found".despite i am passing correct method name

  46. Sraven says:

    Vipul your work is just awesome but how can we get the types of method parameters and handle complex types using wsdl can you show us a sample example it would be really helpful.

  47. jannes says:

    Modification made to the DynamicProxy.Close() method.  Before the modification some exceptions were hidden and replaced with.

    The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state

    public class DynamicProxy

    {

       public void Close()

       {

           var state = GetProperty("State") as CommunicationState?;

           if (state.HasValue &&

               state.Value == CommunicationState.Opened)

           {

               CallMethod("Close");

           }

       }

  48. Anyone here solved the "Method not found" issue? I'm sure the method exists. However why do I get that issue?

  49. Poonam says:

    Hi,

    Thanks for this amazing code!!

    I get an error when I use the DynamicProxy.SetProperty Method.

    Any idea how to resolve it?

  50. Poonam says:

    hi,

    Let me explain what Im trying to achieve..

    I have a security token which I got from the STS service. I want to pass this security toke to the WCF service and get some data. I have added this security token to OperationContext.Current.OutgoingMessageHeaders collection.

    When I invoke the method of the WCF service I get below error message:

    The address of the security token issuer is not specified. An explicit issuer address must be specified in the binding for target 'xxx.com/…/XYZService.svc& or the local issuer address must be configured in the credentials.

    When I try to assign the LocalIssuerBinding of the IssuedToken I get error that it is read only.

    Then I thought maybe I can set the ClientCredentials peoperty of the proxy with all the required values.

    When I do SetProperty I get the error "Method 'XYZServiceClient.ClientCredentials' not found."

    Any pointers??

  51. Manikanta says:

    Hi Vipul,

    I am creating a Dynamic wcf test client. when I browsed in net I found most of the people talking about you and your code. It is very important project for me.

    can you share your code with me. I need some guidance because I am new to wcf  but I am trying my level best to do. So please guide me dude.

  52. Firstly: Amazing work :)

    Secondly: It seems to only return the first message body member instead of returning the response message (as I would prefer). How do I change this (I don't mind getting my hands dirty in the source)?

    Also, how do I perform authorisation?

    Thanks

  53. Vijay says:

    When we pass Custom object as parameter, it is giving error method not found. Please help us.

  54. luiz says:

    Hi, i´m also facing missing method exception.

    Anyone knows how to fix it?

    TKS

  55. Hello Vijay / luiz

    For that ObjectInstance to be used like..

    proxy.CallMethod("methodName", DynamicObj.ObjectInstance);

  56. kalikoi says:

    ive been using this library and it works amazing…ive used for WCF service and am able to get the the input parameters(class file here) for my methods…my class file here is inherited from base class…so when i try to get the properties used am getting some one unknown like propertynamespecified etc..ie for eg if i have property name as UserStatus..i get UserStatus and UserStatusSpecified …is there any way to get only the names ive used..?

    DynamicProxy dp = factory.CreateProxy(contractName);

           Type proxyType = dp.ProxyType;

           MethodInfo method = proxyType.GetMethod(methodName);

           ParameterInfo[] inputParameters = method.GetParameters();

           foreach (ParameterInfo pinfo in inputParameters)

           {

               DynamicProxyClass requestProxy = new DynamicProxyClass(factory.ProxyAssembly, pinfo.ParameterType.ToString());

               Type requestType = pinfo.ParameterType;

               foreach (PropertyInfo propertyInfo in requestType.GetProperties())

               {

                   Response.Write(propertyInfo.Name );

               }

           }

           dp.Close();

    earlier help is highly appreciated..

  57. Math says:

    Hi, great work!

    How can i peform authentication?

    Tks!

  58. Muhammad Talal Shoaib says:

    Thanks for creating such a nice and useful tool. I was having some problems regarding the namespace in the proxy, I mean it was not able to compile the generated proxy, then I modified the code..and it worked :)

    Thanks…

    I had included the following line of code in AddStateForDataContractSerializerImport method in DynamicProxyFactory class.

    xsdDataContractImporter.Options.Namespaces.Add("*", "MyNamespace_Name");

  59. Gowtham Reddy says:

    HI, Its working Great but when I pass a custom object as a parameter, its throwing exception can any body place an example how to call a Service method with CustomClass as a Parameter, Its urgent

    Thanks in Advance

  60. Lukasz says:

    Hi, It looks like all the links stoped working. Is there any other place where I can download library from ?

  61. Naresh says:

    Hi Vipul,

    Thanks for this excellent post. I have one problem though. If my wsdl is such that I have ReplyAction = * in OperatonContract, then while calling any of the method, it throws me the error "Method not found". If I add that service reference to my client, everything works fine, I also added a code to show the method names inside the proxy, I am able to find the function to be called.

    I further researched this problem and found that there is some issue with ReplyAction = *. The WSDL to be called is a third party wsdl and I have no control to change the corresponding ReplyAction property.

    Are you aware of any such problem. Any help in this regard would be appreciated.

    Thanks in advance

    Naresh

  62. Lukas says:

    Hi Vipul,

      Is it possible to get the project sources? The download page seems to be inaccessible.

  63. tinu73 says:

    Is the code still available. Download link seems to be broken

  64. DynamicFlauzer says:

    The download page seems to be inaccessible. Is there another link avaiable?

    Thank