【问题标题】:How to change WebService code behind class dynamically?如何动态更改类后面的WebService代码?
【发布时间】:2013-12-14 22:48:33
【问题描述】:

我在使用不同版本的 Web 服务时遇到问题。

由于 Web 服务有多个版本,有时会更改参数和/或添加和删除 WebMethods。

我想要一个单一的 asmx 文件,但取决于客户端安装(他们正在运行的版本),能够在运行时更改 asmx 背后的代码。

不用每个版本都有不同的 asmx,只需一个 asmx 文件,该文件可以动态加载包含准确版本的代码。在这种情况下,我确实有一个 V1Methods.cs、V2Methods.cs、V10Methods.cs

<%@ WebService Language="C#"  Class="DynamicClass" %>

如果客户运行的是Version2,class后面的asmx代码应该是V2Methods.cs等等。

有可能吗?

【问题讨论】:

  • 您如何知道您的客户端运行的是什么版本?典型的 REST API 将使用 URL 方案来区分版本。
  • 在这种情况下,会有一个配置文件,在设置过程中,用户将被要求输入产品的版本(与 API 版本或 WSDL 相关联)。也就是说,我试图通过拥有一个 EndPoint 来实现一种适合所有人的尺寸。主要问题是版本之间的 WSDL 有巨大的变化。
  • ASMX 是一项遗留技术,不应用于新开发。 WCF 或 ASP.NET Web API 应该用于 Web 服务客户端和服务器的所有新开发。一个提示:微软已经在 MSDN 上停用了ASMX Forum
  • @JohnSaunders 虽然我同意您的观点,但我们的想法是继续使用遗留服务,因为客户端(甚至是 Eclipse 插件和 Visual Studio 插件)旨在支持它们。但是,很难让一种尺寸适合所有人。
  • 为什么您认为客户端不支持使用basicHttpBinding 的WCF 服务?没有必要被困在过去。

标签: c# web-services asmx


【解决方案1】:

简而言之,不,这是不可能的。我本来建议使用 web 服务作为外观,但听上去每个版本上的方法签名不同,这会使其变得更加困难。

如果客户端应用程序依赖于您的 Web 服务的特定版本,您不能只部署具有不同名称的所有服务版本(即 servicev1.asmx、servicev2.asmx 等),并向您的客户端添加一些配置告诉它该调用哪一个?

【讨论】:

  • 您好,这可能是另一种选择。如果客户端设计为始终寻找特定服务,那么这种方法将不起作用(我的意思是,如果客户端是旨在始终发现该服务名称)。因为 Web 服务由不同技术的多个客户端使用,所以无论如何我都会对其进行测试。谢谢你的回答,真的很感激。
  • 实际上我也在考虑创建一种路由器,它应该加载当前类并暴露 WebMethods,但公平地说,我还没有弄清楚如何去做。
  • 客户端“设计为总是寻找特定的服务”——这里的问题是您无法访问他们的源代码吗?
【解决方案2】:

好的 - 我为您提供了一个可能的解决方案,该解决方案并未因优雅而获奖,但我刚刚对其进行了测试,它确实有效。

您可以公开一个返回 object 并接受 params object[] 参数的 WebMethod,允许您将任何您喜欢的内容传递给它(或不传递任何内容)并返回您想要的任何内容。这使用“anyType”类型编译为合法的 WSDL。

如果您可以根据传递给此方法的参数的数量和数据类型确定要调用哪个实际方法,则可以调用适当的方法并返回您想要的任何值。

服务:-

[WebMethod]
public object Method(params object[] parameters)
{
    object returnValue = null;

    if (parameters != null && parameters.Length != 0)
    { 
        if (parameters[0].GetType() == typeof(string) && parameters[1].GetType() == typeof(int))
        {
            return new ServiceImplementation().StringIntMethod(parameters[0].ToString(), Convert.ToInt32(parameters[1]));
        }
        else if (parameters[0].GetType() == typeof(string) && parameters[1].GetType() == typeof(string))
        {
            return new ServiceImplementation2().StringStringMethod(parameters[0].ToString(), parameters[1].ToString());
        }
    }

    return returnValue;
}

我的测试服务实现类:-

public class ServiceImplementation
{
    public string StringIntMethod(string someString, int someInt)
    {
        return "StringIntMethod called";
    }
}

public class ServiceImplementation2
{
    public float StringStringMethod(string someString, string someOtherString)
    {
        return 3.14159265F;
    }
}

使用示例:-

    var service = new MyTestThing.MyService.WebService1();

    object test1 = service.Method(new object[] { "hello", 3 });
    Console.WriteLine(test1.ToString());

    object test2 = service.Method(new object[] { "hello", "there" });
    Console.WriteLine(test2.ToString());

我已经对此进行了测试,并且可以正常工作。如果您有兴趣,“方法”生成的 WSDL:-

POST /test/WebService1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Method"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <Method xmlns="http://tempuri.org/">
      <parameters>
        <anyType />
        <anyType />
      </parameters>
    </Method>
  </soap:Body>
</soap:Envelope>

如果你想知道,是的,我在工作中很无聊,我很想帮助别人:)

【讨论】:

  • 感谢您花时间在这里,我认为这种方法可能有效,我可以使用 AST 编写一些脚本来生成带有参数数组的 WebMethods。实际上取决于参数。因为我会有一个带有版本的配置文件,所以我知道要调用什么实现。谢谢。
  • 经过一番测试,我认为问题更大。通过查看代理的两个不同版本(v1 和 v3),我可以看到在 V3 中删除了一些 WebMethod,并在 V1 中使用了它们。如果我使用版本 3 中的所有方法,那么其他一些方法将不可用。因为客户端被设计为使用当前 API 中的某些特定方法,每个版本都增加了复杂性,因为 WebMethods 被删除或添加,我没有看到除了在运行时生成代理之外的任何其他选项。
猜你喜欢
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 2017-11-17
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多