ASP.NET Mono: как отправить SOAP вместо HTML? - PullRequest
2 голосов
/ 21 февраля 2012

У меня есть веб-сервис ASP.NET на основе SOAP, созданный поверх Mono. Если я выбрасываю исключения внутри службы, исключения остаются на уровне HTTP + HTML. Я хотел бы всегда отправлять все исключения в виде SOAP-ответов, то есть у меня нет нормальных aspx-страниц (все должно работать с SOAP).

Я пытался обработать все исключения в файле Global.asax.cs в методе Application_Error(), но, похоже, он всегда отправляет исключения в виде HTML. Я вижу общую страницу ошибок ASP.NET.

Мой SOAP-клиент, когда он указывает на HTML, сообщает мне, что не может анализировать HTML.

Отправка SOAP с сервера работает хорошо, когда не генерируются исключения.

Я изучил различные веб-источники и узнал, что Application_Error не следует использовать для обработки исключений SOAP из этого ресурса: Обработка и создание исключений в веб-службах XML

Должен ли я реализовать свой собственный модуль HTTP или ExceptionUtility Class или HTTP-обработчик?

Я запускаю это на своей машине для разработки: Информация о версии: Mono Runtime Version: 2.10.5 (Debian 2.10.5-1); ASP.NET версия: 4.0.30319.1

Я тестирую это с помощью встроенного xsp HTTP-сервера MonoDevelop в Ubuntu 11.10.

Вот мой тестовый код:

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

1 Ответ

0 голосов
/ 22 февраля 2012

Во-первых, теория

Application_Error никогда не запускается в соответствии с требованиями .NET Framework. Это связано с тем, что конвейер, который запускает страницы, отличается от того, который запускает веб-сервисы. Также обратите внимание, что выбрасывать исключения в Application_Error - очень плохая идея.

Я обнаружил, что тестирование веб-служб из браузера (где, и, вероятно, , потому что , заголовок accept не установлен на application/soap+xml, а на text/html), приводит к появлению открытого текста. Если клиент является прокси-сервером SOAP (т.е. вы сгенерировали в Visual Studio / MonoDevelop из WSDL веб-службы) и наследует от SoapHttpClientProtocol, то ожидается , что исключение всегда выдается как SOAP fault.

Во-вторых, практика.

Вы делаете var f = new Foo() из Application_Start. Это неверно, поскольку скелетный класс веб-службы создается свежо новым при каждом HTTP / SOAP-запросе и никогда не должен инициализироваться в специальном методе Application_Start, который запускается в самом первом запросе и без обработки самого запроса. Кроме того, вы должны избегать , чтобы делать сложные вещи (которые могут вызвать исключения) в конструкторе веб-службы. Это просто плохой дизайн, а не некомпилируемое или нерабочее решение.

Возможно, ваша проблема возникает из-за того, что конвейер ASP.NET никогда не достиг точки, в которой запрос сопоставлен с обработчиком веб-службы, а не с обработчиком страницы, что вызывает поведение по умолчанию. Пытался найти код в моно репозитории, не повезло:)

Я предлагаю вам сначала удалить любую инициализацию WS в Application_Start, и если вы сказали, что она вам действительно не нужна, выбросьте Application_Error

...