7

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

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

有没有人有比这更好的主意?

4

5 回答 5

7

您可以使用SoapExtensionReflector类修改 WSDL。从柯克埃文斯博客

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 文件中有关 Web 服务文档的问题,2002 年 8 月。

于 2009-07-02T04:37:35.957 回答
2

XMLRPC 已经死了,不是吗?

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

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

于 2009-05-31T00:34:22.880 回答
2

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

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

于 2009-06-03T21:10:15.227 回答
1

它必须是 SOAP 接口吗?听起来它可能更适合基于路由/REST/etc 的 API。您可以IController.Execute很容易地在 ASP.NET MVC 中执行某些操作(使用将操作解析为方法的自定义方法)(事实上,我目前正在为我自己的一些代码处理非常相似的事情)。

例如,您可能有路线:

http://myserver/myservice/mymethod

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

于 2009-05-30T22:21:21.790 回答
0

这是一个建议:

于 2009-07-06T10:52:08.660 回答