动态发现和调用 Web 服务






4.71/5 (34投票s)
如何在不使用添加/Web引用的情况下调用Web服务

引言
通常,当我们使用Web服务时,首先应该在Web引用中添加它,然后静态地调用其方法。 尽管速度很快,但它不够灵活。
为了通过动态调用Web服务来做到这一点,它具有非常好的灵活性。 例如,程序的源代码将被编译一次。
我们可以使用任何我们需要Web服务。 我们可以观察所有Web服务的方法和参数,自动分配方法和参数。
通常,程序员可以使用此方法完成任何工作。 像其他方法一样,在这种方法中,为了实现参数的灵活性,速度会降低。 但是花费的时间比获得的好处要多。
Using the Code
与Web服务通信的一种方法是设置。 通过WSDL文件提供有关Web服务的信息。 要完成这项工作,我们应该生成一个WebRequest
并将其发送到WSDL。 有关各部分的所有活动均由WebRequest
完成。
通过调用Web请求中的GetRequest
方法,WebRequest
将生成一个stream
,该流将被发送到服务描述对象的read
方法。 Read
方法返回一个服务描述对象,该对象包含有关WSDL中Web服务的信息。 我们可以调用Web服务方法,了解Web的说明并使用代理类。
生成代理类的目标是制作类似于将放入*Reference.cs*的代码。 当用户在Visual Studio中添加Web引用并进行编译时,他/她可以通过应用程序中的程序集文件使用它。 第一步是制作一个服务描述导入器的实例,其目标是提供从WSDL读取信息并将其添加到codeDom.CodeCompilement
的能力。 在生成服务描述导入器之后,我们调用add service。 Describe方法并将其发送到包含有关我们决定调用它的Web服务的信息的服务描述对象。 现在我们有了一个程序集文件,其方法和属性来自Web服务。 代理类中显示的所有方法都在主代码中的Web方法属性中。 这些类库具有一种方法,该方法从methodInfo
返回一个对象数组到程序,我们可以从中选择一些方法并通过使用parameterInfo
类来获取它们的参数。 为了调用Web方法,我们需要生成一个代理类的实例,该实例通过Activator,createinstance
类提供Web服务信息的类型。
为了完成这项工作,我们应该将参数列表发送到Invoke
方法,这是预期的。
private void DynamicInvocation()
{
Uri uri = new Uri(textBox1.Text);
WebRequest webRequest = WebRequest.Create(uri);
System.IO.Stream requestStream = webRequest.GetResponse().GetResponseStream();
// Get a WSDL file describing a service
ServiceDescription sd = ServiceDescription.Read(requestStream);
string sdName = sd.Services[0].Name;
// Initialize a service description servImport
ServiceDescriptionImporter servImport = new ServiceDescriptionImporter();
servImport.AddServiceDescription(sd, String.Empty, String.Empty);
servImport.ProtocolName = "Soap";
servImport.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
CodeNamespace nameSpace = new CodeNamespace();
CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
codeCompileUnit.Namespaces.Add(nameSpace);
// Set Warnings
ServiceDescriptionImportWarnings warnings = servImport.Import(nameSpace, codeCompileUnit);
if (warnings == 0)
{
StringWriter stringWriter = new StringWriter
(System.Globalization.CultureInfo.CurrentCulture);
Microsoft.CSharp.CSharpCodeProvider prov = new Microsoft.CSharp.CSharpCodeProvider();
prov.GenerateCodeFromNamespace(nameSpace, stringWriter, new CodeGeneratorOptions());
// Compile the assembly with the appropriate references
string[] assemblyReferences = new string[2]
{ "System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters param = new CompilerParameters(assemblyReferences);
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.TreatWarningsAsErrors = false;
param.WarningLevel = 4;
CompilerResults results = new CompilerResults(new TempFileCollection());
results = prov.CompileAssemblyFromDom(param, codeCompileUnit);
Assembly assembly = results.CompiledAssembly;
service = assembly.GetType(sdName);
methodInfo = service.GetMethods();
foreach (MethodInfo t in methodInfo)
{
if (t.Name == "Discover")
break;
treeWsdl.Nodes[0].Nodes.Add(t.Name);
}
treeWsdl.Nodes[0].Expand();
}
}
Wsdl 文件
在互联网上,您可以找到许多Web服务的wsdl文件,例如
- http://www.webservicex.net/stockquote.asmx?WSDL
- https://w3schools.org.cn/webservices/tempconvert.asmx?WSDL
- http://services.aonaware.com/DictService/DictService.asmx?WSDL
- http://www.xignite.com/xQuotes.asmx?WSDL
谢谢
- 感谢Faramaz Safi(我的老师)的指导
