2009-05-30 55 views
7

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

现在,我已经能够提出的最佳方案是(运行时)生成代表Web服务的C#代码,使用System.Reflection.Emit进行编译,然后在运行时加载程序集 - 所有每当脚本添加或删除服务的方法(不应该经常发生,请注意)。

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

回答

5

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

当您的类型被反映出来为您的服务提供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); 
     } 
     } 
    } 
} 

此添加到配置/ System.Web程序部在web.config中:

<webServices> 
    <soapExtensionReflectorTypes> 
     <add type="TestWebservice.MyReflector, TestWebservice" /> 
    </soapExtensionReflectorTypes> 
</webServices> 

这应该给你一个动态从WSDL文档中删除方法的出发点。如果禁用,您还需要从Web方法中抛出NotImplementedException。

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

1

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

例如,你可能有路线:

http://myserver/myservice/mymethod 

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

+0

感谢您的快速响应 - 不幸的是它必须是SOAP。我直到现在都在使用XMLRPC,但与不愿使用XMLRPC的第三方接口意味着我必须用SOAP来玷污它。 :( – 2009-05-30 22:24:37

+0

嗯......“祝你好运...” – 2009-05-30 22:25:59

2

XMLRPC已经死了,不是吗?

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

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

2

您可以创建与xs:any的输入和输出类型的WCF服务和处理传入的请求为原料Message。这将允许您接受任何类型的数据并返回任何类型的数据。您不会使用数据合同或静态类型,只需要输入Message和输入Message即可。

这种方法的问题是,从WSDL生成代理确实没有什么帮助消费者提供包装来调用方法。提供方法可接受的数据将需要手动滚动的数据类型等,这并不困难,但它不像一个硬性的打字合同那么直观。