📜 ⬆️ ⬇️

.Net MVC 3 logging in 30 minutes

The presence of a logging system is a legal phenomenon for a long time. It allows you how to protect you from unreasonable accusations in your direction, and to be able to recover lost data.

The proposed method does not claim to be universal for all cases, but is a simple and fairly informative method of logging with minimal costs for its implementation.

Introductory


Imagine that you are developing an application that does not have a technical task. Requirements and functionality are constantly changing. And the definitions of what is what is not always fixed. Those. you can change everything at any moment. The project involves a bunch of MSSQL + ASP.Net MVC3 + scripts on the UI (wherever without them). The connection to the database is organized through Linq. It is also an important condition that the connection from the web application to the database comes from one user.
And by the time spelling is very little.
')
What are the solution options?


I chose the solution path - the logging path at the web application level.
So what do we need.

1. Create a table in MSSQL
2. Write classes for logging and the simplest repository
3. Implement the handler in Global.asax.cs


1. Creating a table in MSSQL

Everything is simple:
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/ BEGIN TRANSACTION SET QUOTED_IDENTIFIER ON SET ARITHABORT ON SET NUMERIC_ROUNDABORT OFF SET CONCAT_NULL_YIELDS_NULL ON SET ANSI_NULLS ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON COMMIT BEGIN TRANSACTION GO CREATE TABLE dbo.Log ( LogID bigint NOT NULL IDENTITY (1, 1), UserName nchar(100) NOT NULL, IP nchar(20) NOT NULL, Controller nchar(200) NOT NULL, Action nchar(100) NOT NULL, Number int NOT NULL, Field nchar(100) NOT NULL, Value nchar(1000) NOT NULL, CreateDate datetime NOT NULL, GUID nchar(40) NOT NULL ) ON [PRIMARY] GO ALTER TABLE dbo.Log ADD CONSTRAINT DF_Log_CreateDate DEFAULT getdate() FOR CreateDate GO ALTER TABLE dbo.Log ADD CONSTRAINT PK_Log PRIMARY KEY CLUSTERED ( LogID ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO ALTER TABLE dbo.Log SET (LOCK_ESCALATION = TABLE) GO COMMIT 


2. Classes for logging

You will need the table mapping class + repository.

Class to display the table:
 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Linq.Mapping; namespace %Namespace%.Models.Log { [Table(Name="Log")] public class Log { [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)] public long LogID { get; set; } [Column()] public string UserName { get; set; } [Column()] public string IP { get; set; } [Column()] public string Controller { get; set; } [Column()] public string Action { get; set; } [Column()] public int Number { get; set; } [Column()] public string Field { get; set; } [Column()] public string Value { get; set; } [Column()] public string GUID { get; set; } } } 


Repository class:
 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Linq; namespace %Namespace%.Models { public class LogRepository { protected Table< Log > table; public LogRepository (DataContext dataContext) { table = dataContext.GetTable< Log >(); } public void Add(Log entity) { table.InsertOnSubmit(entity); } public void SubmitChanges() { table.Context.SubmitChanges(); } } } 


3. Hang the handler in Global.asax.cs on the PreRequestHandlerExecute event

 protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) { if (Request.RequestContext.RouteData.Values["controller"] == null) return; LogRepository logRepo = new LogRepository(new DataContext(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString)); string Controller = (Request.RequestContext.RouteData.Values["controller"]!=null?Request.RequestContext.RouteData.Values["controller"].ToString():"PanelSpecifications"); string Action = (Request.RequestContext.RouteData.Values["action"]!=null?Request.RequestContext.RouteData.Values["action"].ToString():"Index"); int counter = 0; string IP = Request.UserHostAddress; string UserName = User.Identity.Name; string GUID = Guid.NewGuid().ToString(); // start mark logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = "StartLog", Value = "StartLog", GUID = GUID } ); counter++; // full route data foreach (var item in Request.RequestContext.RouteData.Values) { if(item.Key.Trim().ToLower() != "controller" && item.Key.Trim().ToLower() != "action") { logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = item.Key??"", Value = Convert.ToString(item.Value)??"" , GUID = GUID } ); counter++; } } // Request Query String foreach (string key in Request.QueryString.Keys) { string Value = Convert.ToString(Request.QueryString[key]); logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = key??"", Value = Value??"" , GUID = GUID } ); counter++; } // Request Form Values foreach (string key in Request.Form.Keys) { string Value = Convert.ToString(Request.Form[key]); logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = key??"", Value = Value??"" , GUID = GUID } ); counter++; } // save changes logRepo.SubmitChanges(); } 


Actually, everything is ready. Now all actions will be recorded.
And you can always answer such familiar questions:
1. "Who is to blame?"
2. "Who did this?"
3. “And this is definitely not a program? I didn’t run data reformatting! ”
Etc.

The method is quite simple, but you somehow close the logging hole. And if you look closely at what fields and how are filled in the table, you will understand that it covers a sufficient part of the questions.

Source: https://habr.com/ru/post/127784/


All Articles