动态C#.NET Web服务

8
我正在一个C# ASP.NET项目中使用一个类,允许用某种随机脚本语言编写的脚本动态地暴露webservice方法 - 换句话说,该脚本应该能够通过此SOAP接口向外界公开任何名称和任何签名的方法(只要它是有效的),并且可以随意添加和删除它们,而无需进行硬编码更改。因此,在C#中需要能够创建webservice类,并能够在运行时动态添加和删除方法。
目前,我想到的最好的计划是(运行时)生成C#代码来表示webservice,使用System.Reflection.Emit进行编译,然后在运行时加载程序集 - 每当脚本添加或删除服务中的方法时都要这样做(不过这种情况应该不会经常发生)。
有没有比这更好的想法?
5个回答

8
您可以使用SoapExtensionReflector类来修改WSDL。根据Kirk Evans博客

当反射您的类型以提供服务的WSDL定义时,将调用SoapExtensionReflector。 您可以利用此类型拦截反射调用并修改WSDL输出。

以下示例删除了2个Web服务方法中的第一个方法:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
   [WebMethod]
   public string HelloWorld()
   {
      return "Hello World";
   }

   [WebMethod]
   public int Multiply(int a, int b)
   {
      return a * b;
   }
}

创建一个继承自SoapExtensionReflector的类:
namespace TestWebservice
{
   public class MyReflector : SoapExtensionReflector
   {
      public override void ReflectMethod()
      {
         //no-op
      }

      public override void ReflectDescription()
      {
         ServiceDescription description = ReflectionContext.ServiceDescription;
         if (description.PortTypes[0].Operations.Count == 2)
            description.PortTypes[0].Operations.RemoveAt(0);
         if (description.Messages.Count == 4)
         {
            description.Messages.RemoveAt(0);
            description.Messages.RemoveAt(0);
         }
         foreach (Binding binding in description.Bindings)
         {
            if (binding.Operations.Count == 2)
               binding.Operations.RemoveAt(0);
         }
         if (description.Types.Schemas[0].Items.Count == 4)
         {
            description.Types.Schemas[0].Items.RemoveAt(0);
            description.Types.Schemas[0].Items.RemoveAt(0);
         }
      }
   }
}

将以下内容添加到web.config文件的configuration/system.web部分:
<webServices>
   <soapExtensionReflectorTypes>
      <add type="TestWebservice.MyReflector, TestWebservice" />
   </soapExtensionReflectorTypes>
</webServices>

这应该为您提供一个起点来动态删除WSDL文档中的方法。如果禁用了Web方法,您还需要从中抛出NotImplementedException。
最后,您需要禁用通过调用.asmx端点生成的Web服务文档,而不使用?WSDL参数。将wsdlHelpGenerator元素的href属性设置为某个URL。您可以使用DefaultWsdlHelpGenerator.aspx作为自己文档处理程序的起点。有关Web服务文档的问题,请参见XML Files,2002年8月中的问题。

2

XMLRPC 已经基本上被淘汰了,不是吗?

SOAP 暗示着需要 WSDL。如何动态生成 WSDL?

您应该考虑使用 WCF。我相信您将能够控制生成 WSDL(和其他元数据)的过程,同时您还应该能够控制处理传入消息的过程。特别地,您将能够检查传入的消息以确定要运行哪个脚本,传递哪些参数等。


据我所知,XMLRPC并没有死亡,只是与SOAP不在同一个“市场”上。选择XMLRPC是因为它需要一个简单而动态的接口,易于人类阅读/编辑。已经围绕这个做了很多开发 - 所以现在,不幸的是,我们有一个使用XMLRPC编写的项目和一个固执的第三方,他们拒绝在无法让Visual Studio为他们工作的情况下做任何事情。 :( - Fritz H
有趣。根据http://en.wikipedia.org/wiki/XML-RPC,我一直觉得自从XML-RPC演变成SOAP后,它已经有点成为了“恐龙”。 - John Saunders

2
您可以创建一个输入输出类型为xs:any的WCF服务,并将传入的请求处理为原始的Message。这将允许您接受任何类型的数据并返回任何类型的数据。您不需要使用数据契约或静态类型,只需一个传入的Message和一个传出的Message
使用这种方法的问题在于,从WSDL生成代理实际上没有什么帮助,除了提供一个调用方法的包装器。提供可接受该方法的数据将需要手动编写数据类型等,这并不难,但与硬编码的类型契约相比,不太直观。

1

它必须是一个SOAP接口吗?那听起来可能更适合于基于路由/REST等的API。你可以很容易地在ASP.NET MVC中完成一些工作(使用自定义的IController.Execute方法解析操作到方法),实际上,我现在正在为我自己的代码开发非常类似的东西。

例如,您可能有以下路由:

http://myserver/myservice/mymethod

接受有效载荷(参数)(通过正文或args)并在响应中返回结果的函数。在非MVC中,您可以使用通配符映射的通用处理程序来执行类似操作。


谢谢您的快速回复 - 不幸的是,它必须是SOAP。我一直在使用XMLRPC,但与一个不愿意使用XMLRPC的第三方接口意味着我必须用SOAP来玷污它。 :( - Fritz H

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接