动态 C#.NET Web 服务

发布于 2024-07-22 20:27:55 字数 359 浏览 4 评论 0原文

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

现在,到目前为止我能想到的最好的计划是(运行时)生成 C# 代码来表示 Web 服务,使用 System.Reflection.Emit 对其进行编译,然后在运行时加载程序集 - 所有这些都在脚本添加时进行或者从服务中删除一个方法(注意,不应该经常发生)。

还有人有比这更好的主意吗?

I am using a class in a C# ASP.NET project to allow a script written in some random scripting language to expose webservice methods dynamically - in other words, the script should be able to expose a method of any name with any signature (as long as it's valid, anyway) to the outside world through this SOAP interface (able to add and remove them at will, without needing a hard code change), and as such I need to be able to create a webservice class in C# while being able to dynamically add and remove methods at runtime.

Now, the best plan I've been able to come up with so far is (runtime) generating C# code to represent the webservice, using System.Reflection.Emit to compile it and then loading the assembly at runtime - all whenever the script adds or removes a method to/from the service (should not happen very often, mind).

Does anyone have a better idea than this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

慈悲佛祖 2024-07-29 20:27:55

您可以使用 SoapExtensionReflector 修改 WSDL班级。 来自 柯克·埃文斯博客

当您的类型被反射以提供服务的 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。

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

You can modify WSDL by using SoapExtensionReflector class. From Kirk Evans Blog:

The SoapExtensionReflector is called when your type is being reflected over to provide the WSDL definition for your service. You can leverage this type to intercept the reflection call and modify the WSDL output.

The following example removes the first method out of 2 web service methods:

[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;
   }
}

Create a class inherited from 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);
         }
      }
   }
}

Add this to configuration/system.web section in web.config:

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

This should give you a starting point to dynamically removing methods from WSDL document. You would also need to throw NotImplementedException from web method if it is disabled.

Finally, you need to disable web service documentation produced by invoking .asmx endpoint without ?WSDL parameter. Set href attribute of wsdlHelpGenerator element to some URL. You can use DefaultWsdlHelpGenerator.aspx as a starting point for your own documentation handler. See question on web service documentation in XML Files, August 2002.

心房敞 2024-07-29 20:27:55

XMLRPC 已经死了,不是吗?

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

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

XMLRPC is fairly dead, isn't it?

SOAP implies a WSDL. How do you generate the WSDL dynamically?

You should look into using WCF. I expect you'll be able to take control of the process of generating the WSDL (and other metadata), yet you should also be able to take control of the processing of incoming messages. In particular, you will be able to examine the incoming messages to determine which script to run, what parameters to pass, etc.

晨光如昨 2024-07-29 20:27:55

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

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

You could create a WCF service with an input and output type of xs:any and handle the incoming request as a raw Message. That would allow you to accept any type of data and return any type of data. You would not use data contracts or static types, just a Message in and a Message out.

The problem with this approach is that generating a proxy from the WSDL really does nothing to help the consumer other than provide a wrapper to call the method. Providing data that is acceptable to the method would require hand-rolling data types, etc which is not that hard, it is just not as intuitive as a hard, typed contract.

殤城〤 2024-07-29 20:27:55

它必须是 SOAP 接口吗? 听起来它可能更适合基于路由/REST/等的 API。 您可以在 ASP.NET MVC 中非常轻松地执行某些操作(使用自定义的 IController.Execute 方法来解析该方法的操作)(事实上,我正在为 我自己的一些代码此刻)。

例如,您可能有routes:

http://myserver/myservice/mymethod

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

Does it have to be a SOAP interface? That sounds like it might be more suitable to a route/REST/etc based API. You could do something in ASP.NET MVC (with a custom IController.Execute method that resolves the action to the method) pretty easily (in fact, I'm working on something very similar for some of my own code at the moment).

For example, you might have routes:

http://myserver/myservice/mymethod

that accepts (either in the body or args) the payload (parameters), and returns the result in the response. In non-MVC you should be able to do something similar with a wildcard-mapped generic handler.

最单纯的乌龟 2024-07-29 20:27:55

这里有一个建议:

Here is a suggestion:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文