动态C#.NET Web服务

时间:2009-05-30 22:17:26

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

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

现在,我能够提出的最好的计划是(运行时)生成C#代码来表示webservice,使用System.Reflection.Emit编译它然后在运行时加载程序集 - 所有这一切脚本在服务中添加或删除方法(不应经常发生,请注意)。

有没有人有比这更好的想法?

5 个答案:

答案 0 :(得分:5)

您可以使用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方法中抛出NotImplementedException。

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

答案 1 :(得分:2)

XMLRPC已经死了,不是吗?

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

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

例如,您可能有路线:

http://myserver/myservice/mymethod

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

答案 4 :(得分:0)

这是一个建议: