2

I'm new to .Net MVC. I've designed a web application using Ado.Net CRUD operation without entity framework. I've searched on the internet on how to implement audit trails on .Net MVC application, but I'm getting results on the implementation of Audit trails on EF application. Can someone provide any resource reference or example? Thank you guys in advance!

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Build your own? A very simplistic version would be an audit table where you log which user has edited which entity at some given time and which were the values changed. If you have CRUD repositories, they can push these information to the audit table. – trashr0x Jun 30 '20 at 14:21
  • 1
    @trashr0x thanks for your response, can you explain with a simple example or reference for capturing user visited pages and actions performed. I agree with your point we can use database triggers for logging any changes to the database tables. But I need to capture the user visited page and action performed on that page. For example, if a user edited a record I need to capture old values and new values of the record – Katta Omkareshwar Jun 30 '20 at 15:40
  • @KattaOmkareshwar the question is unclear as what you ask (tracking web site users) has little to do with ADO.NET or EF. Web sites track users for decades. The simplest "audit" trail is provided by the web server's log. Each action maps to a different URL so a log analyzer can make a pretty good approximation of how a user moves in an application. Other tools (like App Insights) inject tracking scripts allowing them to track even script actions. That's how they're able to show you a user's path through an application. – Panagiotis Kanavos Jan 08 '21 at 08:47
  • What information do you need in your audit trail? For example you may need all sql statements executed or you may need the changes done on table rows or perhaps you need all information about http request. Please be specific. – Jesús López Jan 13 '21 at 18:49

2 Answers2

3

I need to capture the user visited page and action performed on that page

You can implement an HttpModule which logs all the visited pages within your .NET MVC application.

With an HttpModule you have access to all the Request/Response properties, including Headers, Cookies, FormData parameters.

namespace MyApplication
{
    public class DatabaseAuditHttpModule : IHttpModule
    {
        private class Properties
        {
            public string Url { get; set; }
            public string HttpMethod { get; set; }
            public int StatusCode { get; set; }
            
            // add other important HTTP properties
        }
        
        public void Init(HttpApplication context)
        {
            context.BeginRequest += BeginRequest;
            context.EndRequest += EndRequest;
        }

        private void BeginRequest(object sender, EventArgs e)
        {
            HttpContext ctx = HttpContext.Current;
            var request = ctx.Request;

            var requestHeaders = request.Unvalidated.Headers;
            var requestFormData = request.Unvalidated.Form;

            var properties = new Properties
            {
                Url = request.Url.ToString(),
                HttpMethod = request.HttpMethod
            };

            ctx.Items["X-Properties"] = properties;
        }


        private void EndRequest(object sender, EventArgs e)
        {
            HttpContext ctx = HttpContext.Current;

            // get the properties for the current HTTP request
            Properties properties = (Properties)HttpContext.Current.Items["X-Properties"];

            properties.StatusCode = ctx.Response.StatusCode;
            
            // TODO:
            // log these values in the database
        }

        public void Dispose()
        {

        }
    }
}

Registering the HttpModule in Global.asax:

namespace MyApp.Mvc
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            
        }
 
        // register DatabaseAuditHttpModule
        public static DatabaseAuditHttpModule AuditHttpModule = new DatabaseAuditHttpModule();
 
        public override void Init()
        {
            base.Init();
 
            AuditHttpModule.Init(this);
        }
    }
}

Logging stored procedures execution example:

public class DatabaseService
{
    public static async Task ExecuteStoredProcedureAsync(string connectionString, string storedProcedureName, ILogger logger)
    {
        logger.LogTrace($"'{storedProcedureName}' Stored Procedure executing");
        long totalDuration = 0;

        Stopwatch sw = new Stopwatch();
        sw.Start();

        using(var connection = new SqlConnection(connectionString))
        {
            connection.Open();
            
            sw.Stop();
            totalDuration += sw.ElapsedMilliseconds;

            logger.LogTrace($"connection.Open() Duration:{sw.ElapsedMilliseconds}");

            sw.Restart();
            
            using (var command = SqlCommand(storedProcedureName, connection))
            {
                command.CommandType = CommandType.StoredProcedure;

                using (var reader = await command.ExecuteReaderAsync())
                {
                    sw.Stop();
                    totalDuration += sw.ElapsedMilliseconds;

                    logger.LogTrace($"'{storedProcedureName}' Stored Procedure ExecuteReader Duration:{sw.ElapsedMilliseconds}");

                    sw.Restart();

                    do
                    {
                        while (await reader.ReadAsync())
                        {
                            // read the data
                        }

                    } while (await reader.NextResultAsync());
                }

                sw.Stop();
                totalDuration += sw.ElapsedMilliseconds;

                logger.LogTrace($"'{storedProcedureName}' Stored Procedure executed. Duration:{totalDuration}");

                return result;
            }
        }
    }
}
Catalin
  • 11,503
  • 19
  • 74
  • 147
  • Need to capture audit log of ado.net calls(DML) to the database specially stored procedure? – Ashish Kumar Jaryal Jan 08 '21 at 09:03
  • In this case, I suggest you use a built-in SDK which helps you log all these details. You can have a look over [KissLog](https://github.com/KissLog-net/KissLog.Sdk) - it's an SDK I build for the purpose of monitoring .NET apps. (Disclaimer: I am de developer of KissLog). – Catalin Jan 08 '21 at 09:06
  • Any sample code auditing ado.net stored procedure(DML) and DML queries will be very helpful. – Ashish Kumar Jaryal Jan 08 '21 at 10:43
  • Check the updated answer. This is a basic example of using a logger to track Stored Procedure execution. – Catalin Jan 08 '21 at 11:01
  • Okay. Will it be able to track(audit) the old or new values changes in the sql server tables from the stored procedure DML Statements? If not, then how I may get the audit of new or old values of the sql server tables content triggered from the ado.net stored procedure? – Ashish Kumar Jaryal Jan 08 '21 at 11:11
  • 1
    To track the actual Database changes, you will have to do it from the Database level. This cannot be achieved from within the .NET application. Check [Is there a MySQL option/feature to track history of changes to records?](https://stackoverflow.com/questions/12563706/is-there-a-mysql-option-feature-to-track-history-of-changes-to-records) – Catalin Jan 08 '21 at 11:14
  • NOTE: [You can do SQL Profiling from .Net](https://www.codeproject.com/Articles/20173/MS-SQL-Server-Profiler-with-NET). This is great, worth a GitHub page. One suggestion is using an AOP framework and wrapping methods with Attributes. – Jeremy Thompson Jan 11 '21 at 23:58
1

If you are using MS SQL you can look at Change Data Capture or you can track changes using triggers.

This will have to be done on SQL server level though.

Track Data Changes (SQL Server)

I would recommend Change Data Capture. You can access the changes made to tables and also include historic data changes

SQL Server 2019 (15.x) provides two features that track changes to data in a database: change data capture and change tracking. These features enable applications to determine the DML changes (insert, update, and delete operations) that were made to user tables in a database. Change data capture and change tracking can be enabled on the same database; no special considerations are required. For the editions of SQL Server that support change data capture and change tracking, see Features Supported by the Editions of SQL Server 2016. Change tracking is supported by SQL Database. Change data capture is only supported in SQL Server and Azure SQL Managed Instance.

Change Data Capture Change data capture provides historical change information for a user table by capturing both the fact that DML changes were made and the actual data that was changed. Changes are captured by using an asynchronous process that reads the transaction log and has a low impact on the system.

or

Have a look at using triggers.

Understanding Change Tracking in SQL Server using Triggers

As you might be aware, a trigger in a database is a simple program that is executed when an event occurs. We are going to leverage this concept and execute a trigger whenever a record in a table is either inserted, updated, or deleted. If you have a very big database, you can control which columns or tables to install the triggers on. This gives greater control over the other inbuilt techniques for implementing change tracking in SQL Server.

Sakkie
  • 136
  • 8
  • Hello and welcome to SO! Please read the [tour](https://stackoverflow.com/tour), and [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) Adding links is great. But it is much better to show how they solve the question. – Tomer Shetah Jan 12 '21 at 07:01
  • 1
    Thanks @TomerShetah will have a look at links and keep it in mind – Sakkie Jan 12 '21 at 08:29