问题
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