0

After calling Webservices, it returns an object (This object is a custom object class) to client. So, I want to convert from this object to custom class.

-Webservices:

[WebMethod]
public Cls_ROLES GetRoles(int firstNum)
{
    Cls_ROLES o = new Cls_ROLES();
    o.Role_ID = 2;
    o.RoleName = "binh";
    return o;
}

-Client:

+Function:

public object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args)
{
    System.Net.WebClient client = new System.Net.WebClient();
    //-Connect To the web service
    using (System.IO.Stream stream = client.OpenRead(webServiceAsmxUrl + "?wsdl"))
    {
        //--Now read the WSDL file describing a service.
        ServiceDescription description = ServiceDescription.Read(stream);
        ///// LOAD THE DOM /////////
        //--Initialize a service description importer.
        ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
        importer.ProtocolName = "Soap12"; // Use SOAP 1.2.
        importer.AddServiceDescription(description, null, null);
        //--Generate a proxy client. importer.Style = ServiceDescriptionImportStyle.Client;
        //--Generate properties to represent primitive values.
        importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
        //--Initialize a Code-DOM tree into which we will import the service.
        CodeNamespace nmspace = new CodeNamespace();
        CodeCompileUnit unit1 = new CodeCompileUnit();
        unit1.Namespaces.Add(nmspace);
        //--Import the service into the Code-DOM tree. This creates proxy code
        //--that uses the service.
        ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
        if (warning == 0) //--If zero then we are good to go
        {
            //--Generate the proxy code 
            CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
            //--Compile the assembly proxy with the appropriate references
            string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
            CompilerParameters parms = new CompilerParameters(assemblyReferences);
            CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
            //-Check For Errors
            if (results.Errors.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                foreach (CompilerError oops in results.Errors)
                {
                    sb.AppendLine("========Compiler error============");
                    sb.AppendLine(oops.ErrorText);
                }
                throw new System.ApplicationException("Compile Error Occured calling webservice. " + sb.ToString());
            }
            //--Finally, Invoke the web service method 
            Type foundType = null;
            Type[] types = results.CompiledAssembly.GetTypes();
            foreach (Type type in types)
            {
                if (type.BaseType == typeof(System.Web.Services.Protocols.SoapHttpClientProtocol))
                {
                    Console.WriteLine(type.ToString());
                    foundType = type;
                }
            }

            object wsvcClass = results.CompiledAssembly.CreateInstance(foundType.ToString());
            MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
            object o = new object();
            o=mi.Invoke(wsvcClass, args);
            return o;
        }
        else
        {
            return null;
        }
    }
}

+Page_Load function:

Line 1:object[] args=new object[1];
Line 2:args[0]=1;  
Line 3:o = this.CallWebService("http://localhost:1814/HelloServices/Service.asmx", "Hello", "GetRoles", args);

it returns an object at Line3 (This object is a custom object class) to client. So, I want to convert from this object to custom class(Cls_Role object). //====================================================================================== //====================================================================================== //====================================================================================== As Selalu_Ingin_Belajar's answer,I can get value from webservices to client fine.

object yourObject = new object();

foreach (PropertyInfo property in yourObject.GetType().GetProperties())
{           
    object value = property.GetValue(yourObject , null);
    Console.WriteLine("{0} = {1}", property.Name, value);
}

Beside it,When I apply to another project,It show another error: Parameter count mismatch. If I use AddWebReference by VisualStudio tool. It'll auto generate Reference.cs file.It contain:

/// <remarks/>
    [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:ALBAPI", ResponseNamespace="urn:ALBAPI")]
    [return: System.Xml.Serialization.SoapElementAttribute("info")]
    public ResponseInfo getSetupLicenseRows(out SetupLicenseRowsValues values) {
        object[] results = this.Invoke("getSetupLicenseRows", new object[0]);
        values = ((SetupLicenseRowsValues)(results[1]));
        return ((ResponseInfo)(results[0]));
    }

So that,It's easy to call from webClient by passing a object SetupLicenseRowsValues class. Now,I must pass parameter to WebServices by manually.Don't use this generate file.

Client:

public object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args)
        {
            System.Net.WebClient client = new System.Net.WebClient();
            //-Connect To the web service
            using (System.IO.Stream stream = client.OpenRead(webServiceAsmxUrl + "?wsdl"))
            {
                //--Now read the WSDL file describing a service.
                ServiceDescription description = ServiceDescription.Read(stream);
                ///// LOAD THE DOM /////////
                //--Initialize a service description importer.
                ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
                importer.ProtocolName = "Soap12"; // Use SOAP 1.2.
                importer.AddServiceDescription(description, null, null);
                //--Generate a proxy client. importer.Style = ServiceDescriptionImportStyle.Client;
                //--Generate properties to represent primitive values.
                importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
                //--Initialize a Code-DOM tree into which we will import the service.
                CodeNamespace nmspace = new CodeNamespace();
                CodeCompileUnit unit1 = new CodeCompileUnit();
                unit1.Namespaces.Add(nmspace);
                //--Import the service into the Code-DOM tree. This creates proxy code
                //--that uses the service.
                ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
                if (warning == 0) //--If zero then we are good to go
                {
                    //--Generate the proxy code 
                    CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
                    //--Compile the assembly proxy with the appropriate references
                    string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
                    CompilerParameters parms = new CompilerParameters(assemblyReferences);
                    CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
                    //-Check For Errors
                    if (results.Errors.Count > 0)
                    {
                        StringBuilder sb = new StringBuilder();
                        foreach (CompilerError oops in results.Errors)
                        {
                            sb.AppendLine("========Compiler error============");
                            sb.AppendLine(oops.ErrorText);
                        }
                        throw new System.ApplicationException("Compile Error Occured calling webservice. " + sb.ToString());
                    }
                    //--Finally, Invoke the web service method 
                    Type foundType = null;
                    Type[] types = results.CompiledAssembly.GetTypes();
                    foreach (Type type in types)
                    {
                        if (type.BaseType == typeof(System.Web.Services.Protocols.SoapHttpClientProtocol))
                        {
                            Console.WriteLine(type.ToString());
                            foundType = type;
                        }
                    }

                    object wsvcClass = results.CompiledAssembly.CreateInstance(foundType.ToString());
                    MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
                    object o = new object();
                    Line error: o = mi.Invoke(wsvcClass, new object[0]);
                    return o;
                }
                else
                {
                    return null;
                }
            }
        }
public void call()
    {
        string WebserviceUrl = "http://192.168.2.19:3333/ALBAPI.wsdl";
        string serviceName = "ALBAPI";
        string methodName = "getSetupLicenseRows";
        object[] args=new object[0];
        object sSessionID = CallWebService(WebserviceUrl, serviceName, methodName,args);
        foreach (PropertyInfo property in sSessionID.GetType().GetProperties())
        {
            object value = property.GetValue(sSessionID, null);

            Console.WriteLine("{0} = {1}", property.Name, value);
        }

    }

Now,It show error "Parameter count mismatch" at Line error. Thanks for your help anyway

Brian
  • 163
  • 2
  • 18
  • 2
    What have you done? Show your effort. – Furqan Safdar Nov 02 '12 at 03:28
  • [Google - Overloading conversion operators C#](https://www.google.com/search?q=c%23+overloading+conversion+operator) – Simon Whitehead Nov 02 '12 at 03:28
  • Why in the world are you calling web services like that? Just use a Service Reference, or a Web Reference if you're still running .NET 2.0. – John Saunders Nov 02 '12 at 04:03
  • 1
    Just want to say thank you, this is very clever and entertaining, although it is a bit insane. – Paul Keister Nov 02 '12 at 04:05
  • @Furqan Safdar:I've studied it within 3weeks,It's very easy if we return a string or a double type from webservices to client.But it seem hard when we want to return a custom class.Thanks – Brian Nov 02 '12 at 04:10
  • But why go for manually building the proxy on every call instead of using a service reference that would be strongly typed? – Pablo Romeo Nov 02 '12 at 04:11
  • @SimonWhitehead: Thanks for your suggestion.It's useful when we perform with default type.When use it in my project.It show "Can't convert from 'Cls_Roles' type to 'Cls_Roles'".Thanks – Brian Nov 02 '12 at 04:12
  • @Pablo Romeo and John Saunders:Thanks for your suggestion.Because my project need to connect to multiple services by input address and port manualy.So that,we can't use AddWebReferen as http://www.carlosfemmer.com/post/2008/01/How-to-add-web-reference-in-VS-2008-Project.aspx link.Thanks – Brian Nov 02 '12 at 04:18
  • @PabloRomeo: May you give me a link for help to build the proxy on every call.Thanks – Brian Nov 02 '12 at 04:21
  • You actually already are creating the proxy on every call. Try using "dynamic" types as mentioned in my answer below. I'll try to expand with an example. – Pablo Romeo Nov 02 '12 at 04:55
  • Now, you do know that even if you add it as a web or service reference, you can still programmatically alter the url and port of the service, correct? – Pablo Romeo Nov 02 '12 at 05:04
  • I wonderd if you have a example for get dynammic type.Thanks bro – Brian Nov 02 '12 at 07:37
  • Yes,I can programmatically alter the url and port of the services If we pass parameter to CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args) function Thanks – Brian Nov 02 '12 at 07:39
  • Oh, that's not what I meant. I mean generating a real proxy using a service reference or web reference. Not dynamically, but using the IDE. And later, when you create the instance of the proxy, just have it point to whichever endpoint you want by changing the Url property (for web reference) or the EndpointAddress in a service reference. – Pablo Romeo Nov 03 '12 at 16:33

3 Answers3

0

Now, if i understood correctly, and since you went through the cumbersome effort of dynamically building the proxy (instead of using service references), that would mean that your consumer code, does not contain an actual definition for any of the objects your possible service may return.

In that case I don't see many ways in which through statically typed code you can accomplish that. You could try using dynamic and hope that your response has the "structure" you expect, but without knowing the real type. Such as:

dynamic returnValue = CallWebservice(someEndpoint, someServiceName, ...);
//now you can access all the properties of returnValue, for example:
Console.WriteLine(returnValue.Role_ID);
//but you won't have intellisense, may be error prone, and will prevent you from proper refactoring
Pablo Romeo
  • 11,298
  • 2
  • 30
  • 58
  • Cannot define a class or member that utilizes 'dynamic' because the compiler required type 'System.Runtime.CompilerServices.DynamicAttribute' cannot be found. Are you missing a reference to System.Core.dll? – Brian Nov 02 '12 at 07:33
  • I think it will be hard for perform it.Because we must to change return type of CallWebservice(..) function. Beside it, Console.WriteLine(returnValue.Role_ID); It'll show error: One or more types required to compile a dynamic expression cannot be found. Are you missing references to Microsoft.CSharp.dll and System.Core.dll? Thanks for helping – Brian Nov 02 '12 at 07:35
  • I don't think you would need to change anything in the CallWebservice function. Are you on C# 4.0? – Pablo Romeo Nov 03 '12 at 16:31
  • Hi bro,I'm on C# 4.0.May you give me any idea.Thanks bro – Brian Nov 05 '12 at 04:16
  • It show error "Parameter count mismatch" at Line error now. I edit something at this description. – Brian Nov 05 '12 at 04:16
  • I'm still a bit lost about why you want to go through all this madness. Just add a Web Reference or Service reference, and then programmatically change the URL to wherever you need to be in runtime. It is very very uncommon to need to dynamically compile and use proxies in this manner. – Pablo Romeo Nov 05 '12 at 04:34
  • Ah,Thanks bro for your answer.My problem must not to use AddWebReference.It mustn't use in my project. Because user have to input information about webservices such as: IPAddress,Port. Then,Client will use this information for access to Webservices.Do you have any idea? – Brian Nov 05 '12 at 04:59
  • Even if the IP address, port, or even protocol are configured through the UI, you can and SHOULD still use a statically created reference. You just need to configure it accordingly in runtime, as i said above in my comments. Just set the Url property if it's a webreference or the endpoint if it's a service reference. See this please: http://stackoverflow.com/a/1193135/1373170 – Pablo Romeo Nov 05 '12 at 05:25
  • Dear friend, I've tried your suggestion. `` BasicHttpBinding binding = new BasicHttpBinding(); EndpointAddress address = new EndpointAddress("http://localhost:8888/MyService"); MyServiceClient serviceClient = new MyServiceClient(binding, address); `$` – Brian Nov 05 '12 at 09:15
  • Dear friend, I've tried your suggestion. `` BasicHttpBinding binding = new BasicHttpBinding(); EndpointAddress address = new EndpointAddress("http://localhost:8888/MyService"); MyServiceClient serviceClient = new MyServiceClient(binding, address); `$` ...............I apply it to my project: ALBAPI obj = new ALBAPI(binding, address);//=====It didn't work.Because my class is defined : public class ALBAPI : SoapHttpClientProtocol.//===Just have a constructor.It's auto generate by Reference.cs file – Brian Nov 05 '12 at 09:32
  • I saw this propertities in ALBAPI class. public ALBAPI(); public string Url { get; set; } public bool UseDefaultCredentials { get; set; } – Brian Nov 05 '12 at 09:52
  • You can trust us, ws proxy urls are indeed configurable. Maybe you can change your question or create a new one with that specific problem, but it is really the common approach to this kind of thing. – Pablo Romeo Nov 06 '12 at 03:33
  • Thanks for sugession,brother.I made a new articles: http://stackoverflow.com/questions/13244829/connect-multiple-server-by-webservices-from-asp-net – Brian Nov 06 '12 at 05:18
0

Simply use Web/Service Reference by right clicking on your client project and discover this Web Service. Provide appropriate namespace name and click OK.

This procedure will automatically generate the Proxy of GetRoles method along with your custom class type Cls_ROLES on your client based on the Schema exposed in WSDL.

Furqan Safdar
  • 16,260
  • 13
  • 59
  • 93
  • Thank bro for suggestion.Because my project need to connect to multiple services by input address and port manualy to a webform.System will save them,afterthat,Using this information for connect to webservices manually.Can't use by your hand for add to visualStudio.So that,we can't use AddWebReferen as carlosfemmer.com/post/2008/01/… link – Brian Nov 02 '12 at 04:35
0

if you just want to get value of every parameter of the object, you can using reflection.

object yourObject = new object();

foreach (PropertyInfo property in yourObject.GetType().GetProperties())
{           
    object value = property.GetValue(yourObject , null);
    Console.WriteLine("{0} = {1}", property.Name, value);
}

but you better using Service Reference like Pablo and Furqan said to get clear schema of your object. Because it will serialize your object automatically , so you dont bother about serialization stuff. Sorry about my english :p

  • Thanks bro,I tried and see it work fine.It show propertyName and value fine.Oh,yep,I'll study it more about serialze.Keep in touch with me,bro.Thanks – Brian Nov 02 '12 at 04:33
  • Hi brother,I got another error.It show error "Parameter count mismatch" at Line error.I edit at this description.Thanks for your help anyway – Brian Nov 05 '12 at 04:14