Как определить тип исключения, генерируемого веб-сервисом asp.net? - PullRequest
5 голосов
/ 18 января 2012

У меня есть веб-сервис asp.NET (не WCF, а классический .asmx с WebMethods), который генерирует исключения. Все исключения происходят из одного из двух базовых классов исключений (оба из которых происходят от исключения):

public class InputException : Exception
{
   ....
}

public class FatalException : Exception
{
    ....
}

public class NoFilesFound: FatalException
{
   ....
}

....

Веб-сервис прямо сейчас выдает исключение по мере необходимости. В моем клиентском коде я могу перехватить исключения и увидеть следующее сообщение:

Server was unable to process request. ---> There were no files found

Однако исключение имеет тип FaultException (как видно, когда я делаю .GetType () для перехваченного исключения). Вызывающий клиент должен иметь возможность различать InputException и FatalException (и оптимально различать отдельные производные, но это не так важно). Прямо сейчас единственный способ сделать это - проанализировать сообщение, убрать текст перед "--->" и включить текст. Это явно не оптимально.

Я знаю, что могу генерировать исключения SoapException с пользовательским кодом, но я хочу избежать этого, если это возможно. Более того, он предназначен для тех, кто имеет дело с XML, но весь наш код веб-сервиса не касается XML, поскольку он уже десериализован для нас.

Итак, вкратце, есть ли у меня способ выбросить пользовательские исключения из веб-сервиса и чтобы вызывающий клиент мог различать исключения?

1 Ответ

7 голосов
/ 18 января 2012

Правильный способ справиться с этим - использовать SoapException .Таким образом, вы будете в основном перехватывать все возможные исключения в сервисе, а затем переводить их в SoapException (документация, на которую я ссылался, содержит пример), а затем вместо того, чтобы выдавать какое-то пользовательское исключение, выбрасывать это SoapException и включать интересующую вас информациюподробный XML-узел ошибки.

Затем при вызове службы на клиенте вы сможете перехватить это SoapException и проанализировать подробный XML-узел, чтобы собрать более подробную информацию о точной причине ошибки, произошедшей насервер.

Вся эта ручная генерация узлов сбоев была очень легко представлена ​​в WCF, где вы просто работаете с контрактами данных и ловите FaultException<SomeFaultContract>.

Давайте рассмотрим пример.Предположим, у вас есть следующий сервисный метод, который генерирует исключение SoapException и предоставляет подробные сведения об ошибке в узле Details:

[WebMethod]
public string HelloWorld()
{
    var doc = new XmlDocument();
    var node = doc.CreateNode(
        XmlNodeType.Element, 
        SoapException.DetailElementName.Name, 
        SoapException.DetailElementName.Namespace
    );
    // you could actually use any sub nodes here
    // and pass even complex objects
    node.InnerText = "no files found";

    throw new SoapException(
        "Fault occurred", 
        SoapException.ClientFaultCode, 
        Context.Request.Url.AbsoluteUri, 
        node
    );
}

при его использовании вы можете перехватить это SoapException на клиенте:

using (var client = new WebService1())
{
    try
    {
        var result = client.HelloWorld();
    }
    catch (SoapException ex)
    {
        var detail = ex.Detail;
        // detail.InnerText will contain the detail message
        // as detail is an XmlNode if on the server you have
        // provided a complex XML you would be able to fetch it here
    }
}

Что касается ваших исключений InputException, FatalException и NoFilesFound, то с ними все в порядке, но они должны оставаться на сервере.Перехватите их в своем веб-методе и создайте правильный SoapException, который клиент сможет понять при использовании службы.

...