【问题标题】:Dynamic C#.NET Webservice动态 C#.NET Web 服务
【发布时间】:2009-05-30 22:17:26
【问题描述】:

我在 C# ASP.NET 项目中使用一个类,以允许用某种随机脚本语言编写的脚本动态地公开 web 服务方法 - 换句话说,脚本应该能够公开具有任何签名的任何名称的方法(只要它是有效的,无论如何)通过这个 SOAP 接口(能够随意添加和删除它们,而不需要硬代码更改),因此我需要能够在 C# 中创建一个 webservice 类同时能够在运行时动态添加和删除方法。

现在,到目前为止,我能想出的最佳计划是(运行时)生成 C# 代码来表示 Web 服务,使用 System.Reflection.Emit 对其进行编译,然后在运行时加载程序集——无论何时脚本在服务中添加或删除方法(不应该经常发生,请注意)。

还有比这更好的主意吗?

【问题讨论】:

    标签: c# asp.net web-services dynamic reflection.emit


    【解决方案1】:

    您可以使用SoapExtensionReflector 类修改 WSDL。来自Kirk Evans Blog

    SoapExtensionReflector 在反射您的类型时调用,以便为您的服务提供 WSDL 定义。您可以利用此类型拦截反射调用并修改 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 方法被禁用,您还需要从 Web 方法中抛出 NotImplementedException。

    最后,您需要禁用通过调用不带 ?WSDL 参数的 .asmx 端点生成的 Web 服务文档。将 wsdlHelpGenerator 元素的 href 属性设置为某个 URL。您可以使用 DefaultWsdlHelpGenerator.aspx 作为您自己的文档处理程序的起点。请参阅XML Files, August 2002 中有关 Web 服务文档的问题。

    【讨论】:

      【解决方案2】:

      XMLRPC 已经死了,不是吗?

      SOAP 意味着一个 WSDL。如何动态生成 W​​SDL?

      您应该考虑使用 WCF。我希望您能够控制生成 WSDL(和其他元数据)的过程,但您也应该能够控制传入消息的处理。特别是,您将能够检查传入的消息以确定要运行的脚本、要传递的参数等。

      【讨论】:

      • 嗯,据我所知,XMLRPC 并没有死,只是它与我认为的 SOAP 不在同一个“市场”中。为这个项目选择了 XMLRPC,因为它需要一个易于人类阅读/编辑的简单且动态的界面。围绕这一点进行了很多开发——所以现在,不幸的是,我们有一个使用 XMLRPC 和一个顽固的第三方编写的项目,它拒绝做任何他们不能让 Visual Studio 为他们完成工作的事情。 :(
      • 有趣。根据en.wikipedia.org/wiki/XML-RPC,在我看来,自从 XML-RPC 演变成 SOAP 之后,它就有点像“恐龙”了。
      【解决方案3】:

      您可以创建一个输入和输出类型为xs:any 的WCF 服务,并将传入请求作为原始Message 处理。这将允许您接受任何类型的数据并返回任何类型的数据。您不会使用数据协定或静态类型,只使用 Message in 和 Message out。

      这种方法的问题在于,从 WSDL 生成代理实际上对消费者没有任何帮助,只是提供了一个包装器来调用该方法。提供该方法可接受的数据将需要手动滚动数据类型等,这并不难,只是不如硬类型合同那么直观。

      【讨论】:

        【解决方案4】:

        它必须是 SOAP 接口吗?听起来它可能更适合基于路由/REST/etc 的 API。你可以很容易地在 ASP.NET MVC 中做一些事情(使用自定义的 IController.Execute 方法来解析方法的动作)(事实上,我目前正在为 some of my own code 做一些非常相似的事情)。

        例如,您可能有路线:

        http://myserver/myservice/mymethod
        

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

        【讨论】:

        • 感谢您的快速响应 - 不幸的是它必须是 SOAP。到目前为止,我一直在使用 XMLRPC,但是与不愿意使用 XMLRPC 的第三方交互意味着我必须使用 SOAP 来污染它。 :(
        【解决方案5】:

        这是一个建议:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-18
          • 1970-01-01
          • 2011-01-30
          • 1970-01-01
          相关资源
          最近更新 更多