【问题标题】:Standalone c# webservice without webserver没有网络服务器的独立 c# webservice
【发布时间】:2014-01-07 09:36:11
【问题描述】:

我想使用 c# 实现一个 Web 服务。我对实现服务器而不是消费者感兴趣。 Web服务必须由独立软件运行,因为我没有IIS之类的Web服务器来部署它。

在 Linux/Unix 中,我知道我可以获取一个 wsdl 文件,我使用 gsoap 为其生成 C 代码,我在服务器端实现例程并构建链接 libgsoap 的独立程序。

现在我想用 c# 和 .net 平台做同样的事情。

我用来研究的wsdl文件和gsoap一样,你可以找到here。

下一步是下载它并运行wsdl -server cal.wsdl以获得calc.cs。

此时我被卡住了,因为我无法找到有关如何 继续。

如何实现扩展我通过运行 wsdl 获得的抽象类 calc 的程序,该 wsdl 启动一个小型 Web 服务器来执行所需的功能?你能指点我一些好的文档吗?

已添加

当我运行 wsdl -server cal.wsdl 时,我得到了这段代码

/// <remarks/>
/// <remarks>
///gSOAP 2.7.9k generated service definition
///</remarks>
[System.Web.Services.WebServiceAttribute(Namespace="http://websrv.cs.fsu.edu/~engelen/calc.wsdl")]
[System.Web.Services.WebServiceBinding(Name="calc", Namespace="http://websrv.cs.fsu.edu/~engelen/calc.wsdl")]
public abstract partial class calc : System.Web.Services.WebService {

    /// <remarks>
///Service definition of function ns__add
///</remarks>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:calc", ResponseNamespace="urn:calc")]
    [return: System.Xml.Serialization.SoapElement("result")]
    public abstract double add(double a, double b);

    /// <remarks>
///Service definition of function ns__sub
///</remarks>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:calc", ResponseNamespace="urn:calc")]
    [return: System.Xml.Serialization.SoapElement("result")]
    public abstract double sub(double a, double b);

    /// <remarks>
///Service definition of function ns__mul
///</remarks>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:calc", ResponseNamespace="urn:calc")]
    [return: System.Xml.Serialization.SoapElement("result")]
    public abstract double mul(double a, double b);

    /// <remarks>
///Service definition of function ns__div
///</remarks>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:calc", ResponseNamespace="urn:calc")]
    [return: System.Xml.Serialization.SoapElement("result")]
    public abstract double div(double a, double b);

    /// <remarks>
///Service definition of function ns__pow
///</remarks>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:calc", ResponseNamespace="urn:calc")]
    [return: System.Xml.Serialization.SoapElement("result")]
    public abstract double pow(double a, double b);
}

这是一个抽象类,因为服务器端的所有方法都没有实现。因此,我希望,与我通常使用 gsoap 所做的类似,我必须扩展这个类并覆盖抽象方法,这很容易。

问题是在那之后我不知道如何编写一个程序来获取继承的类并启动一个 Web 服务器并在网络上公开该 Web 服务。

【问题讨论】:

  • 听起来您正试图从 wsdl 生成 Web 服务实现。这不可能。 wsdl 文件不包含逻辑,它只告诉客户端它需要与服务器通信的方法和类型。
  • 是的,这就是为什么我写在 Linux/Unix 中我用 gsoap 生成 C 代码,在编译之前我还为服务器实现了例程,以便它知道当webservice 被调用。
  • 你问如何编写代码和 C# 并编译它?
  • 不,我只是想了解在所有函数中编写逻辑后如何实例化 Web 服务。检查我添加的代码。
  • 您正在使用 ASMX 技术。 ASMX 是一项遗留技术,不应用于新开发。 WCF 或 ASP.NET Web API 应该用于 Web 服务客户端和服务器的所有新开发。一个提示:Microsoft 已停用 MSDN 上的 ASMX Forum。

标签: c# web-services soap wsdl asmx


【解决方案1】:

这并不复杂,但需要您做一些工作。您可以使用 WCF 技术创建服务。

我想您将使用 Visual Studio 并为 .NET 创建一个应用程序。如果您的目标是 Mono,您将不得不以某种方式采用下面的示例。

1 - 创建一个控制台 .NET 项目并手动添加对 System.ServiceModel 和 System.Runtime.Serialization 的引用。

2 - 您应该将抽象类转换为接口。这将是您工作中最困难的部分,因为您应该因此获得相同的 WSDL。

例如:

[System.Web.Services.WebServiceAttribute(Namespace="http://websrv.cs.fsu.edu/~engelen/calc.wsdl")]
[System.Web.Services.WebServiceBinding(Name="calc", Namespace="http://websrv.cs.fsu.edu/~engelen/calc.wsdl")]
public abstract partial class calc : System.Web.Services.WebService {
/// <remarks>
///Service definition of function ns__add
///</remarks>
[System.Web.Services.WebMethodAttribute()]
[System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:calc", ResponseNamespace="urn:calc")]
[return: System.Xml.Serialization.SoapElement("result")]
public abstract double add(double a, double b); 

转换示例:

using System.ServiceModel;
// other usings, namespace etc

[ServiceContract(Namespace = "http://websrv.cs.fsu.edu/~engelen/calc.wsdl", Name = "calc")]
public interface ICalcService
{
    [OperationContract(Name = "add")]
    [return: MessageParameter(Name = "result")]
    [XmlSerializerFormatAttribute(Style=OperationFormatStyle.Rpc, Use=OperationFormatUse.Encoded)]
    double add(double a, double b);

    // the rest of methods
}

或者,您可以尝试使用 svcutil 生成 C# 代理类:

svcutil http://www.genivia.com/calc.wsdl

您将获得 calc.cs,因此您可以从中提取服务和数据合同。

3 - 无论如何,在您使用服务合同创建接口后,您将创建其实现:

public class CalcServiceImpl : ICalsService
{
    public double add(double a, double b)
    {
        return a + b;
    }

    // the rest
}

4 - 之后您应该创建一个 ServiceHost 实例。像这样:

ServiceHost host = new ServiceHost(typeof(CalcServiceImpl), new Uri("http://myhost/MyServices")))
host.AddServiceEndpoint(typeof(ICalcService), new BasicHttpBinding(), "CalcService");
host.Open();
Console.ReadKey();
host.Close();

当然,这是一个非常简化的例子,但希望能给你指明方向。

【讨论】:

  • 谢谢你的回答,我知道我需要在wsdl文件上运行svcutil来获取代理类。我还有一个问题:一旦我运行了 svcutil calc.wsdl,你能确认我只需要实现接口 calcPortType,然后在步骤 4 中实例化它吗?
  • 基本上是的,但正如我所说,创建接口可能是一个难以破解的难题,因为您的结果服务必须与使用原始 WSDL 生成的客户端兼容。例如,您必须从界面中删除 [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")] 属性,将参数 Name="calc" 添加到 ServiceContractAttribute,应用附加属性 [DataContractFormat(Style = OperationFormatStyle.Rpc)] 到接口等等。我还建议您使用 app.config 来提供服务配置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2011-08-07
相关资源
最近更新 更多