Как перехватить / обработать исключения в WCF, возникающие из-за приведения типа или передачи неверных значений в переменные при вызове через почтальона - PullRequest
0 голосов
/ 30 октября 2019

Я новичок в WCF. При создании RestFul Apis я столкнулся с некоторой проблемой сбоев.

На моей охоте на Обработка исключений через WCF я получил помощь из различных источников, таких как:

Обработка исключений WCFСтратегии https://blogs.msdn.microsoft.com/pedram/2008/01/25/wcf-error-handling-and-some-best-practices/ https://riptutorial.com/csharp/example/5460/implementing-ierrorhandler-for-wcf-services

Благодаря реализации обработчика глобальных ошибок внутренние исключения приложения обрабатываются плавно (обрабатывается ими в try catch catch clock). Но я не уверен, как обрабатывать исключения. Т.е. исключения, вызывающие сбой приложения, если переменная получает недопустимое значение.

РЕДАКТИРОВАТЬ:

У меня есть следующий класс DataContract

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;

namespace StilaarAPI.DataContracts
{
    [DataContract]
    public class Products
    {

        [DataMember]
        [Required(ErrorMessage = "product Name is required")]
        [StringLength(50, MinimumLength = 5, ErrorMessage = "Address Feild length should be between 5 and 50")]
        public string ProductName { get; set; }

        [Required(ErrorMessage = "ProductID is requied")]
        [DataMember]
        public int ProductID { get; set; }



    }
    }


И далее (служба WCF с поддержкой Ajax использует вышеупомянутый класс DataContract в качестве входного аргумента)
[OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
    public string GetProduct(Products pro)
    {
        try
        {

            string test = "Every thing works fine :D";
            return test;

            //ResultDo<List<ProblemTypesDo>> result = new ResultDo<List<ProblemTypesDo>>();
            //var problemTypes = _riderOrderDeliveryBL.GetProblemType();


        }
        catch (NotFoundException ex)
        {
            NotFoundFault fault = new NotFoundFault();
            fault.Error = "Product Not Found";
            fault.StatusCode = HttpStatusCode.NotFound;

            throw new WebFaultException<NotFoundFault>(
                                       fault, HttpStatusCode.NotFound);
        }



    }

Вызов вышеуказанной службы из почтальона просто дает гладкий простой результат:

enter image description here

Что хорошо, теперь, если я запускаю разные входные сценарии для входной переменной: начиная с установки нулевого значения для имени продукта, я получаю следующий результат enter image description here

Неплохо, так как моя проверка работала, а исключение обрабатывалось, поэтому я получил вышеуказанный результат. Теперь, переходя к следующему сценарию, если я установил ID в null, получится следующий вывод: enter image description here

Теперь мой вопрос: что я могу сделать, чтобы предотвратить сбой приложения таким образом? :

Ниже приведены мои классы IError Handler:

public class GlobalErrorBehaviorAttribute : Attribute, IServiceBehavior
{
    private readonly Type errorHandlerType;

    /// <summary>
    /// Dependency injection to dynamically inject error handler if we have multiple global error handlers
    /// </summary>
    /// <param name="errorHandlerType"></param>
    public GlobalErrorBehaviorAttribute(Type errorHandlerType)
    {
        this.errorHandlerType = errorHandlerType;
    }



    #region IServiceBehavior Members

    void IServiceBehavior.Validate(ServiceDescription description,
        ServiceHostBase serviceHostBase)
    {
    }

    void IServiceBehavior.AddBindingParameters(ServiceDescription description,
        ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
    {
    }

    /// <summary>
    /// Registering the instance of global error handler in dispatch behavior of the service
    /// </summary>
    /// <param name="description"></param>
    /// <param name="serviceHostBase"></param>
    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description,
        ServiceHostBase serviceHostBase)
    {
        IErrorHandler errorHandler;

        try
        {
            errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
        }
        catch (MissingMethodException e)
        {
            throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must have a public empty constructor.", e);
        }
        catch (InvalidCastException e)
        {
            throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
        }

        foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
        {
            ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
            channelDispatcher.ErrorHandlers.Add(errorHandler);
        }
    }

    #endregion IServiceBehavior Members



}




 public class GlobalErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {

        return true;
    }

    public void ProvideFault(Exception error,System.ServiceModel.Channels.MessageVersion version,ref System.ServiceModel.Channels.Message fault)
    {

            //if (error is FaultException)
            //    return;

            var jsonError = new CustomFault
            {

                Error = "Something went wrong",
                Details = error.GetType().FullName

            };
            fault = Message.CreateMessage(version, "", jsonError,
                                          new DataContractJsonSerializer(typeof(CustomFault)));

            // Tell WCF to use JSON encoding rather than default XML
            var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

            // Modify response
            var rmp = new HttpResponseMessageProperty
            {
                StatusCode = HttpStatusCode.BadRequest,
                StatusDescription = "Bad Request",
            };
            rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
            fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);


    }
}



public class ExtendedWebHttpBehavior : WebHttpBehavior
{
    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        // clear default erro handlers.
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();

        // add our own error handler.
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new GlobalErrorHandler());
        //BehaviorExtensionElement
    }
}

Когда я ставлю точку останова, чтобы выдать ошибку, она показывает следующее исключение, как если бы оно было из-за синтаксического анализа: enter image description here

Как мне справиться с этим, чтобы я мог отправить чистое сообщение об ошибке клиенту

Редактировать: Почтальон общее исключение:

 ?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">

    <head>
        <title>Request Error</title>
        <style>
            BODY {
                color: #000000;
                background-color: white;
                font-family: Verdana;
                margin-left: 0px;
                margin-top: 0px;
            }

            #content {
                margin-left: 30px;
                font-size: .70em;
                padding-bottom: 2em;
            }

            A:link {
                color: #336699;
                font-weight: bold;
                text-decoration: underline;
            }

            A:visited {
                color: #6699cc;
                font-weight: bold;
                text-decoration: underline;
            }

            A:active {
                color: #336699;
                font-weight: bold;
                text-decoration: underline;
            }

            .heading1 {
                background-color: #003366;
                border-bottom: #336699 6px solid;
                color: #ffffff;
                font-family: Tahoma;
                font-size: 26px;
                font-weight: normal;
                margin: 0em 0em 10px -20px;
                padding-bottom: 8px;
                padding-left: 30px;
                padding-top: 16px;
            }

            pre {
                font-size: small;
                background-color: #e5e5cc;
                padding: 5px;
                font-family: Courier New;
                margin-top: 0px;
                border: 1px #f0f0e0 solid;
                white-space: pre-wrap;
                white-space: -pre-wrap;
                word-wrap: break-word;
            }

            table {
                border-collapse: collapse;
                border-spacing: 0px;
                font-family: Verdana;
            }

            table th {
                border-right: 2px white solid;
                border-bottom: 2px white solid;
                font-weight: bold;
                background-color: #cecf9c;
            }

            table td {
                border-right: 2px white solid;
                border-bottom: 2px white solid;
                background-color: #e5e5cc;
            }
        </style>
    </head>

    <body>
        <div id="content">
            <p class="heading1">Request Error</p>
            <p xmlns="">The server encountered an error processing the request. Please see the <a rel="help-page"
                    href="https://localhost:44326/ServiceContracts/CustomerAccount.svc/help">service help page</a> for
                constructing valid requests to the service.</p>
        </div>
    </body>

    </html>

Исключения отладчика:

Значение '' не может быть проанализировано как тип 'Int32'. {"Средство форматирования выдало исключение при попытке десериализации сообщения: при попытке десериализации параметра произошла ошибка: pro. Сообщение InnerException было« Произошла ошибка при десериализации объекта типа StilaarAPI.DataContracts.Products. Значение »не может быть проанализирован как тип 'Int32'. '. Для получения более подробной информации см. InnerException. "}

1 Ответ

0 голосов
/ 31 октября 2019

Тело запроса не аутентифицировано в локальном формате JSON. Он не удовлетворяет схеме JSON, что означает, что запрос еще не поступил на сервер, поэтому сервер не обрабатывает его в соответствии с интерфейсом IErrorHandler.
Ему должна понравиться приведенная ниже форма, чтобы запрос мог достичьserver.

{"Id":null,"Name":"Apple"}

Не стесняйтесь, дайте мне знать, если я могу чем-то помочь.
Обновлено.
Не вмешиваться в процесс сериализации в IErrorhandlerинтерфейс, пожалуйста, рассмотрите использование следующего кода для обработки ошибок.

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            MyError myerror = new MyError()
            {
                Details = error.Message,
                Error = "Hello"
            };
            fault = Message.CreateMessage(version, "messsagefault", myerror);
        }

Или, мы можем напрямую отправить подробности ошибки.

FaultException faultException = new FaultException(error.Message);
            MessageFault messageFault = faultException.CreateMessageFault();            
            fault = Message.CreateMessage(version, messageFault, error.Message);

Кроме того, мы можем обрабатывать сериализацию сообщений вIClientMessageFormatter / IDispatcherMessageFormatter.
https://docs.microsoft.com/en-us/dotnet/framework/wcf/extending/custom-message-formatters

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...