Get Custom Class from webservices

自闭症网瘾萝莉.ら 提交于 2019-12-25 05:24:09

问题


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


回答1:


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




回答2:


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.




回答3:


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


来源:https://stackoverflow.com/questions/13188860/get-custom-class-from-webservices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!