带有 SOAP 扩展的 ASMX Web 服务

发布于 2024-08-30 00:37:27 字数 2001 浏览 1 评论 0原文

我正在为外部客户端设置 Web 服务,以连接到我的客户端的应用程序并更新一些信息。我选择了 ASMX 路线(应用程序的其余部分在 WCF 上运行),因为我知道外部客户端可能非常难以处理,并且我试图让一切尽可能简单。他们也不是一家 .Net 商店,这让事情变得更糟。在为他们设置服务后,我向他们提供了 ASMX URL,以了解如何格式化 SOAP 标头/消息内容。他们后来回来告诉我他们的工具无法以 .Net 要求的格式发送它们,我可以想出一种不同的方式来接受消息,或者我们必须使用 FTP。

基于此,我一直在研究如何拦截他们的消息,按照我的服务需要的方式重新格式化它(这意味着添加两行),然后让它处理。这条路引导我找到了 SOAP Extensions,我一直在尝试使用它,但似乎无法弄清楚。当我让示例应用程序从生成的代码调用 Web 服务时,添加 Web 引用会提供一切正常的工作,直到我添加扩展为止。它当前所做的就是覆盖 ChainStream,设置一个内部流等于传入的流并返回一个新流,如下所示:

private Stream newStream = null;
private Stream oldStream = null;

public override Stream ChainStream(Stream stream)
{
    this.oldStream = stream;
    this.newStream = new MemoryStream();
    return newStream;
}

我还覆盖 ProcessMessage 并在其中获取 oldStream 的内容并将 newStream 设置为等于该内容,然后写入与 XmlWriter 不同的流。我采用该新流并使用 StreamReader 将其读入字符串,最终目标是在此处对其进行操作并将 newStream (由 ChainStream 使用)设置为等于该内容的内容。这是那部分:

    public override void ProcessMessage(SoapMessage message)
{
    switch (message.Stage)
    {
        case SoapMessageStage.BeforeDeserialize:
            this.Process();
            break;

        default: break;
    }
}

private void Process()
{
    this.newStream.Position = 0L;
    XmlTextReader reader = new XmlTextReader(this.oldStream);
    MemoryStream outStream = new MemoryStream();
    using (XmlWriter writer = XmlWriter.Create(outStream))
    {
        do { writer.WriteNode(reader, true); } while (reader.Read());
        writer.Flush();
    }
    outStream.Seek(0, SeekOrigin.Begin);
    StreamReader streamReader = new StreamReader(outStream);
    string message = streamReader.ReadToEnd();
    newStream = outStream;
    newStream.Seek(0, SeekOrigin.Begin);
    streamReader.Close();

}

通过运行这个(在我看来这会很好),我的测试应用程序从服务返回了 400 Bad Request。如果我不使用扩展或者在 ProcessMessage 中不执行任何操作,那么一切似乎都很好。对此有何建议?

附带说明一下,一旦我使用 WSDL 生成的代码进行工作,我将转向 WebRequest 来尝试将消息发送到服务。目前,该响应会导致 415 Unsupported Media Type 响应失败。我试图将这篇文章保留为一个问题,但如果有人对使用 WebRequest 连接到 ASMX 服务有任何提示,我将不胜感激!

I am in the process of setting up a web service for an external client to connect to my client's application and update some information. I went the ASMX route (the rest of the application runs on WCF) because I knew the external client could be very difficult to deal with and I was trying to keep everything as simple as possible. They also aren't a .Net shop which makes things worse. After getting the service setup for them I provided the ASMX URL for them to see how to format the SOAP headers/message content. They have since come back and told me their tool is unable to send them in the format required by .Net and I can either come up with a different way to accept messages or we have to go with FTP.

Based on this I have been researching how to intercept their message, reformat it the way my service requires it (which means adding two lines), and then let it process. This path led me to SOAP Extensions which I have been trying to work with but can't seem to figure out. When I have my sample application call the web service from the generated code Add Web Reference provides everything works great until I add in my extension. All it currently does is override ChainStream setting an internal stream equal to the one being passed in and returning a new stream, like this:

private Stream newStream = null;
private Stream oldStream = null;

public override Stream ChainStream(Stream stream)
{
    this.oldStream = stream;
    this.newStream = new MemoryStream();
    return newStream;
}

I also override ProcessMessage and in it take the contents of oldStream and set newStream equal to that and then write to a different stream with an XmlWriter. I take that new stream and using a StreamReader read it into a string, with the end goal being manipulating it here and setting newStream (which is being used by ChainStream) equal to the contents of this. Here is that piece:

    public override void ProcessMessage(SoapMessage message)
{
    switch (message.Stage)
    {
        case SoapMessageStage.BeforeDeserialize:
            this.Process();
            break;

        default: break;
    }
}

private void Process()
{
    this.newStream.Position = 0L;
    XmlTextReader reader = new XmlTextReader(this.oldStream);
    MemoryStream outStream = new MemoryStream();
    using (XmlWriter writer = XmlWriter.Create(outStream))
    {
        do { writer.WriteNode(reader, true); } while (reader.Read());
        writer.Flush();
    }
    outStream.Seek(0, SeekOrigin.Begin);
    StreamReader streamReader = new StreamReader(outStream);
    string message = streamReader.ReadToEnd();
    newStream = outStream;
    newStream.Seek(0, SeekOrigin.Begin);
    streamReader.Close();

}

By running this, which seems to me like it would be fine, my test application gets a 400 Bad Request back from the service. If I either don't use the extension or I don't do anything in ProcessMessage everything seems fine. Any suggestions to this?

As a side note, once I get this working with the generated code from the WSDL I will be moving to a WebRequest to try sending the message to the service. Currently that bombs out with a 415 Unsupported Media Type response. I'm trying to keep this post to one question but if anyone has any tips with using a WebRequest to connect to an ASMX service it would be much appreciated!

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

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

发布评论

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

评论(1

淡水深流 2024-09-06 00:37:27

我知道这不是您正在寻找的答案,但为什么不直接使用 REST 而不是 SOAP?由于服务的主要(唯一?)消费者不会遵守,因此尝试“修复”他们的调用只是增加了一层额外的复杂性。

相反,只需使用接受查询字符串上的数据或带有 xml 请求正文的 aspx 页面,对其进行处理,然后将 xml(或其他格式)响应流式传输回给他们。

您失去了自动生成类型信息等的 Visual Studio SOAP“魔力”,但由于他们没有使用(或不承认使用)带有 SOAP 库的语言,这对任何人都没有真正的帮助。

I realise this isn't the answer you're looking for but why not just use REST instead of SOAP? Since the main (only?) consumer of the service isn't going to comply, trying to 'fix' their calls is just an extra layer of complexity.

Instead, just use an aspx page that accepts data on the query string or with an xml request body, process it and then stream the xml (or other format) response back to them.

You lose the Visual Studio SOAP "magic" which auto-generates type info etc. but since they aren't using (or aren't admitting to using) a language with a SOAP library, this doesn't really help anyone.

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