Я хотел бы добавить некоторые общие регистрации в мой веб-API (используемый приложением Angular 7).
Моя идея состоит в том, чтобы создать глобальный фильтр действий для ведения журнала - это то, что я имею до сих пор:
public class GlobalTraceFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
TraceData data = new TraceData
{
ControllerName = actionContext.ControllerContext.ControllerDescriptor.ControllerName,
ActionName = actionContext.ActionDescriptor.ActionName,
RequestType = "Enter"
};
WriteToLog(data);
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
TraceData data = new TraceData
{
ControllerName = actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName,
ActionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName,
RequestType = "Exit"
};
WriteToLog(data);
}
private void WriteToLog(TraceData data)
{
if (data == null)
{
return;
}
try
{
// save metadata
using (SqlCommand cmdInsertTraceData = new SqlCommand("dbo.WebApiRequest_Insert", DB.Connection))
{
cmdInsertTraceData.CommandType = CommandType.StoredProcedure;
cmdInsertTraceData.Parameters.Add("@RequestType", SqlDbType.VarChar, 50).Value = GetValueOrDbNull(data.RequestType);
cmdInsertTraceData.Parameters.Add("@ControllerName", SqlDbType.VarChar, 500).Value = GetValueOrDbNull(data.ControllerName);
cmdInsertTraceData.Parameters.Add("@ActionName", SqlDbType.VarChar, 500).Value = GetValueOrDbNull(data.ActionName);
cmdInsertTraceData.Parameters.Add("@Parameters", SqlDbType.VarChar, 8000).Value = ConvertToXml(data.Parameters);
cmdInsertTraceData.ExecuteNonQuery();
}
}
catch (Exception exc)
{
ErrorSignal.FromCurrentContext().Raise(exc);
}
}
private string ConvertToXml(List<KeyValuePair<string, string>> traceParameters)
{
List<string> parameters = new List<string>();
foreach (var kvp in traceParameters)
{
string paramEntry = $"<parameter name=\"{kvp.Key}\">{kvp.Value}</parameter>";
parameters.Add(paramEntry);
}
return "<parameters>" + string.Join("", parameters) + "</parameters>";
}
private object GetValueOrDbNull(object value)
{
if (value == null)
{
return DBNull.Value;
}
return value;
}
}
Прямо сейчас я получаю две записи - одну для того, когда действие выполнено (OnActionExecuting
- RequestType=Enter
), и другую для того, когда оно завершено (OnActionExecuted
- RequestType=Exit
).
Я хотел бы объединить эти два в одну запись, которая будет записывать действие и имя контроллера, дату / метку времени запроса и ответа, параметр вызова, содержимое ответа (если есть), когда действие сделано и т. д.
Моя проблема в : как и где я могу хранить информацию из OnActionExecuting
(когда вызывается метод действия), чтобы ее можно было дополнить информацией ответа, когда она будет завершена?
Я надеялся, что у меня будет доступ к коллекции HttpContext.Items
или к чему-то похожему (что-то (а) «локальное» для текущего запроса / вызывающего абонента и (б) достаточно «постоянное», чтобы оставаться там до тех пор, пока ответ находится и был обработан) - но этого, кажется, не существует.
Как и где я могу сохранить информацию из OnActionExecuting
и записать ее в журнал только после ответа обработано (в методе OnActionExecuted
)