Нужно регистрировать asp.net webapi 2 тело запроса и ответа в базе данных

Я использую Microsoft Asp.net WebApi2, размещенный в IIS. Я просто хотел бы зарегистрировать тело запроса (xml или json) и тело ответа для каждого сообщения.

Нет ничего особенного в этом проекте или контроллере, обрабатывающем сообщение. Я не заинтересован в использовании фреймворков регистрации, таких как nLog, elmah, log4net или встроенные функции трассировки webapi, если это не необходимо.

Я просто хочу знать, где поставить код регистрации и как получить фактический json или xml из входящего и исходящего запроса и ответа.

Мой метод отправки почты:

public HttpResponseMessage Post([FromBody])Employee employee)
{
   if (ModelState.IsValid)
   {
      // insert employee into to database
   }

}

Ответ 1

Я бы порекомендовал использовать DelegatingHandler. Тогда вам не нужно беспокоиться о каком-либо коде регистрации в ваших контроллерах.

public class LogRequestAndResponseHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // log request body
        string requestBody = await request.Content.ReadAsStringAsync();
        Trace.WriteLine(requestBody);

        // let other handlers process the request
        var result = await base.SendAsync(request, cancellationToken);

        if (result.Content != null)
        {
            // once response body is ready, log it
            var responseBody = await result.Content.ReadAsStringAsync();
            Trace.WriteLine(responseBody);
        }

        return result;
    }
}

Просто замените Trace.WriteLine вашим кодом регистрации и зарегистрируйте обработчик в WebApiConfig следующим образом:

config.MessageHandlers.Add(new LogRequestAndResponseHandler());

Вот полная документация Microsoft для обработчиков сообщений.

Ответ 2

Существует несколько подходов к общей обработке журнала запросов/ответов для каждого вызова метода WebAPI:

  • ActionFilterAttribute: Можно написать пользовательский ActionFilterAttribute и украсить методы контроллера/действия, чтобы включить ведение журнала.

    Con: вам нужно украсить каждый контроллер/методы (все же вы можете сделать это на базовом контроллере, но все же он не затрагивает проблемы перекрестных ссылок.

  • Переопределите BaseController и выполните регистрацию там.

    Con: Мы ожидаем/вынуждаем контроллеры наследовать от пользовательского базового контроллера.

  • Использование DelegatingHandler.

    Преимущество: Мы не трогаем контроллер/метод здесь с таким подходом. Делегирующий обработчик сидит изолированно и грациозно обрабатывает журнал запросов/ответов.

Для получения более подробной статьи обратитесь к http://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi.

Ответ 3

Один из вариантов, который у вас есть, - это создание фильтра действий и оформление им вашего WebApiController/ApiMethod.

Атрибут фильтра

public class MyFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.Request.Method == HttpMethod.Post)
            {
                var postData = actionContext.ActionArguments;
                //do logging here
            }
        }
    }

Контроллер WebApi

[MyFilterAttribute]
public class ValuesController : ApiController{..}

или же

[MyFilterAttribute]
public void Post([FromBody]string value){..}

Надеюсь это поможет.

Ответ 4

Получение доступа к запросу - это просто. Ваш базовый класс ApiController содержит .Request свойство, который, как следует из названия, содержит запрос в разобранной форме. Вы просто проверяете его на все, что вы ищете, чтобы регистрировать его и передавать его на ваш объект регистрации, какой бы он ни был. Этот код можно ввести в начале действия, если вам нужно сделать это только для одного или нескольких.

Если вам нужно сделать это на всех действиях (все значения больше, чем управляемая часть), то то, что вы можете сделать, это переопределить метод .ExecuteAsync для захвата каждого вызова действия для вашего контроллера.

public override Task<HttpResponseMessage> ExecuteAsync(
    HttpControllerContext controllerContext,
    CancellationToken cancellationToken
)
{
    // Do logging here using controllerContext.Request
    return base.ExecuteAsync(controllerContext, cancellationToken);
}