ASP.NET Mono:如何发送 SOAP 而不是 HTML?

发布于 2025-01-07 20:05:13 字数 2830 浏览 0 评论 0原文

我有一个基于 SOAP 的 ASP.NET Web 服务,构建在 Mono 之上。 如果我在服务内部抛出异常,异常将保留在 HTTP+HTML 级别。我想要做的就是始终将所有异常作为 SOAP 响应发送,即我没有任何正常的 aspx 页面(一切都应该与 SOAP 一起工作)。

我尝试在 Application_Error() 方法中处理 Global.asax.cs 文件中的所有异常,但它似乎总是以 HTML 形式发送异常。 我看到的是通用 ASP.NET 错误页面。

当我的 SOAP 客户端指向 HTML 时,它通知我它无法解析 HTML。

当没有抛出异常时,从服务器发送 SOAP 效果很好。

我研究了各种 Web 资源,并了解到 Application_Error 不应该用于来自此资源的 SOAP 异常处理: 处理和引发 XML Web 服务中的异常

我必须实现自己的 HTTP 模块还是 ExceptionUtility 类 或 HTTP 处理程序?

我在我的开发机器上运行这个: 版本信息:Mono运行时版本:2.10.5(Debian 2.10.5-1); ASP.NET 版本:4.0.30319.1

我正在 Ubuntu 11.10 中使用 MonoDevelop 的内置 xsp HTTP 服务器对此进行测试。

这是我的测试代码:

Global.asax.cs:

using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.SessionState;
using System.Web.Services.Protocols;

namespace SoapTaikina
{
    public class Global : System.Web.HttpApplication
    {
        protected virtual void Application_Start (Object sender, EventArgs e)
        {
            Backend.Initialize();
        }

        protected virtual void Application_Error (Object sender, EventArgs e)
        {
            // This doesn't appear to be executed when Foo() throws an exception.
            // I cannot catch the Foo() constructor exception here.
            throw new SoapException("This is never reached.", null);
        }

        // These are not used in this example.
        protected virtual void Session_Start (Object sender, EventArgs e) { }
        protected virtual void Application_BeginRequest (Object sender, EventArgs e) { }
        protected virtual void Application_EndRequest (Object sender, EventArgs e) { }
        protected virtual void Application_AuthenticateRequest (Object sender, EventArgs e) { }
        protected virtual void Session_End (Object sender, EventArgs e) { }
        protected virtual void Application_End (Object sender, EventArgs e) { }
    }
}

Foo.asmx.cs:

using System;
using System.Web;
using System.Web.Services;

namespace SoapTaikina
{
    public class Foo : System.Web.Services.WebService
    {
        public Foo()
        {
            // This may throw an Exception which will not be caught in
            // Application_Error().
            //
            // This is the problem spot.
            Backend2.InitializeMoreStuff();
        }

        [WebMethod]
        public bool DoStuff() {
            // This works fine and returns a SOAP response.
            return true;
        }
    }
}

I have an ASP.NET web service based on SOAP built on top of Mono.
If I throw exceptions inside the service, the exceptions remain on the HTTP+HTML level. What I'd like to do is send always all exceptions as SOAP responses, i.e. I don't have any normal aspx pages (everything should work with SOAP).

I've tried handling all exceptions in the Global.asax.cs file within the Application_Error() method, but it seems to always send the exceptions as HTML.
What I see is the generic ASP.NET error page.

My SOAP client, when pointed to the HTML, informs me that it cannot parse HTML.

Sending SOAP from the server works nicely when no exceptions are thrown.

I've studied various web sources and learned that Application_Error shouldn't be used for SOAP exception handling from this resource:
Handling and Throwing Exceptions in XML Web Services

Do I have to implement my own HTTP Module or
ExceptionUtility Class or HTTP Handler?

I am running this on my development machine:
Version information: Mono Runtime Version: 2.10.5 (Debian 2.10.5-1); ASP.NET Version: 4.0.30319.1

I am testing this with MonoDevelop's built-in xsp HTTP server inside Ubuntu 11.10.

Here is my test code:

Global.asax.cs:

using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.SessionState;
using System.Web.Services.Protocols;

namespace SoapTaikina
{
    public class Global : System.Web.HttpApplication
    {
        protected virtual void Application_Start (Object sender, EventArgs e)
        {
            Backend.Initialize();
        }

        protected virtual void Application_Error (Object sender, EventArgs e)
        {
            // This doesn't appear to be executed when Foo() throws an exception.
            // I cannot catch the Foo() constructor exception here.
            throw new SoapException("This is never reached.", null);
        }

        // These are not used in this example.
        protected virtual void Session_Start (Object sender, EventArgs e) { }
        protected virtual void Application_BeginRequest (Object sender, EventArgs e) { }
        protected virtual void Application_EndRequest (Object sender, EventArgs e) { }
        protected virtual void Application_AuthenticateRequest (Object sender, EventArgs e) { }
        protected virtual void Session_End (Object sender, EventArgs e) { }
        protected virtual void Application_End (Object sender, EventArgs e) { }
    }
}

Foo.asmx.cs:

using System;
using System.Web;
using System.Web.Services;

namespace SoapTaikina
{
    public class Foo : System.Web.Services.WebService
    {
        public Foo()
        {
            // This may throw an Exception which will not be caught in
            // Application_Error().
            //
            // This is the problem spot.
            Backend2.InitializeMoreStuff();
        }

        [WebMethod]
        public bool DoStuff() {
            // This works fine and returns a SOAP response.
            return true;
        }
    }
}

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

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

发布评论

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

评论(1

暗藏城府 2025-01-14 20:05:13

首先,理论上

根据 .NET Framework 的要求,Application_Error 永远不会被触发。这是因为运行页面的管道与运行 Web 服务的管道不同。另外,请注意,在 Application_Error 中抛出异常是一个非常糟糕的主意。

我发现从浏览器测试 Web 服务(其中可能因为,接受标头未设置为 application/soap+xml 而是设置为 text/html< /code>) 使出现明文消息。如果客户端是 SOAP 代理(即您在 Visual Studio/MonoDevelop 中从 Web 服务的 WSDL 生成)并继承自 SoapHttpClientProtocol,则预期始终将异常作为 SOAP 错误< /代码>。

第二,练习。

您可以从 Application_Start 执行 var f = new Foo()。这是错误的,因为 Web 服务骨架类是在每个 HTTP/SOAP 请求上全新实例化的,并且永远不应该在第一个请求上运行且没有请求本身的特殊 Application_Start 方法中进行初始化尚未处理。另外,您应该避免在 Web 服务的构造函数中执行复杂的操作(可能会引发异常)。这只是一个糟糕的设计,而不是一个无法编译或无法工作的解决方案。

出现问题的原因可能是 ASP.NET 管道从未达到将请求映射到 Web 服务处理程序而不是页面处理程序的程度,从而触发默认行为。尝试在 Mono 存储库中找到代码,但没有成功:)

我建议您首先删除 Application_Start 中的所有 WS 初始化,如果您说您并不真正需要它,请扔掉 Application_Error

First, theory

Application_Error is never fired according to .NET Framework requirements. This is because the pipeline that runs pages is different from the one that runs web services. Also, notice that throwing exceptions in Application_Error is a very bad idea.

I found that testing web services from the browser (where, and probably because, accept header is not set to application/soap+xml but to text/html) makes a plaintext message appear. If the client is a SOAP proxy (ie you generated in Visual Studio/MonoDevelop from the web service's WSDL) and inherits from SoapHttpClientProtocol then it is expected that the exception is always thrown as SOAP fault.

Second, practice.

You do var f = new Foo() from Application_Start. This is wrong because the web service skeleton class is instantiated fresh new on every HTTP/SOAP request, and should never be initialized in the special Application_Start method that is run on the very first request and without the request itself bein processed yet. Also, you should avoid to do complex things (that may throw exceptions) in web service's constructor. This is just a bad design, not a non-compiling or non-working solution.

Your problem probably occurs because the ASP.NET pipeline never reached the point where the request is mapped to a web service handler rather than a page handler, firing default behaviour. Tried to find the code in mono repository, no luck :)

I suggest you to first remove any WS initialization in Application_Start, and if you said you don't really need it, throw away Application_Error

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