Empty IQueryable Class
Enumerable.Empty<ClassName>().AsQueryable();
Store Allowed Domains in appsettings.json: Instead of hardcoding the allowed domains in the code, we can define them in the configuration file:
{ "AllowedOrigins": [ "https://app1.example.com", "https://app2.example.com", "https://mobile.example.com" ] }
Retrieved the array of allowed origins from the app settings and used them to register CORS services :
string allowedSpecificOrigins = "AllowSpecificOrigins"; WebApplicationBuilder? builder = WebApplication.CreateBuilder(args); string[]? allowedOrigins = builder .Configuration .GetSection("AllowedOrigins") .Get<string[]>(); builder.Services.AddCors(options => { options.AddPolicy(allowedSpecificOrigins, policy => { policy.WithOrigins(allowedOrigins) .AllowAnyMethod() .AllowAnyHeader(); }); }); builder.Services.AddControllers();
Enable CORS middleware
app.UseCors(allowedSpecificOrigins);
This configuration ensures that all LINQ queries using Include() in Entity Framework Core are executed using split queries by default. This helps prevent performance issues caused by Cartesian explosion when loading multiple related collections. It is enabled by setting UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery) in the DbContext configuration.
builder.Services.AddDbContext<YourDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")) .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery) );
To enable Server GC, modify the runtimeconfig.json file or add the following to your app settings:
{ "runtimeOptions": { "configProperties": { "System.GC.Server": true } } }
Alternatively, you can configure GC in ASP.NET Core apps by editing Program.cs:
public static void Main(string[] args) { var host = Host.CreateDefaultBuilder(args) .UseServerGC() // Enables Server GC mode .Build(); host.Run(); }
Extract File Signature —
Validate Against Expected Format: —
Perform Additional Security Checks
Define Allowed File Signatures: -
Each file type has a unique signature (byte sequence) at the beginning of the file. Below are some common file signatures:
Define a dictionary to map file types to their signatures:
public static class FileSignatures { public static readonly Dictionary<string, List<byte[]>> Signatures = new() { { ".jpg", new List<byte[]> { new byte[] { 0xFF, 0xD8, 0xFF } } }, { ".png", new List<byte[]> { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } }, { ".pdf", new List<byte[]> { new byte[] { 0x25, 0x50, 0x44, 0x46 } } }, { ".docx", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } } // DOCX is a ZIP file format }; }
Validate File Signature During Upload: —
Use the file stream to read the first few bytes and compare them against the allowed signatures.
public static bool IsValidFileSignature(Stream fileStream, string fileExtension) { if (!FileSignatures.Signatures.ContainsKey(fileExtension)) return false; // File type is not allowed var allowedSignatures = FileSignatures.Signatures[fileExtension]; using (var reader = new BinaryReader(fileStream)) { foreach (var signature in allowedSignatures) { fileStream.Position = 0; // Reset stream position before reading var headerBytes = reader.ReadBytes(signature.Length); if (headerBytes.SequenceEqual(signature)) return true; // Valid file signature } } return false; // Invalid file signature }
Implement File Validation in Controller : —
Modify the file upload controller to validate the file signature before saving.
[HttpPost("upload")] public async Task<IActionResult> UploadFile(IFormFile file) { if (file == null || file.Length == 0) return BadRequest("File is empty."); var extension = Path.GetExtension(file.FileName).ToLowerInvariant(); using var fileStream = file.OpenReadStream(); if (!IsValidFileSignature(fileStream, extension)) return BadRequest("Invalid file format."); var filePath = Path.Combine("Uploads", file.FileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } return Ok("File uploaded successfully."); }
switch (mark) { case int n when n >= 80: Console.WriteLine("Grade is A"); break; case int n when n >= 60: Console.WriteLine("Grade is B"); break; case int n when n >= 40: Console.WriteLine("Grade is C"); break; default: Console.WriteLine("Grade is D"); break; }
Install Elmah Package from Nuget.
Now open web config file and add the following code inside <system.web> </system.web>.
<!--add this--> < httpHandlers > < add verb = "POST,GET,HEAD"path = "elmah.axd"type = "Elmah.ErrorLogPageFactory, Elmah" / > < /httpHandlers> <!--add this-->
Also, add the following code inside <system.webServer></system.webServer>.
<!--add this--> < handlers > < add name = "Elmah"verb = "POST,GET,HEAD"path = "elmah.axd"type = "Elmah.ErrorLogPageFactory, Elmah" / > < /handlers> <!--add this-->
Create ELMAH_Error table.
CREATE TABLE[dbo].[ELMAH_Error] ( [ErrorId][uniqueidentifier] NOT NULL, [Application][nvarchar](60) NOT NULL, [Host][nvarchar](50) NOT NULL, [Type][nvarchar](100) NOT NULL, [Source][nvarchar](60) NOT NULL, [Message][nvarchar](500) NOT NULL, [User][nvarchar](50) NOT NULL, [StatusCode][int] NOT NULL, [TimeUtc][datetime] NOT NULL, [Sequence][int] IDENTITY(1, 1) NOT NULL, [AllXml][ntext] NOT NULL )
Create stored procedures.
ELMAH_GetErrorsXml
Create PROCEDURE[dbo].[ELMAH_GetErrorsXml] ( @Application NVARCHAR(60), @PageIndex INT = 0, @PageSize INT = 15, @TotalCount INT OUTPUT ) AS SET NOCOUNT ON DECLARE @FirstTimeUTC DATETIME DECLARE @FirstSequence INT DECLARE @StartRow INT DECLARE @StartRowIndex INT SELECT @TotalCount = COUNT(1) FROM [ELMAH_Error] WHERE [Application] = @Application SET @StartRowIndex = @PageIndex * @PageSize + 1 IF @StartRowIndex <= @TotalCount BEGIN SET ROWCOUNT @StartRowIndex SELECT @FirstTimeUTC = [TimeUtc], @FirstSequence = [Sequence] FROM [ELMAH_Error] WHERE [Application] = @Application ORDER BY [TimeUtc] DESC, [Sequence] DESC END ELSE BEGIN SET @PageSize = 0 END SET ROWCOUNT @PageSize SELECT errorId = [ErrorId], application = [Application], host = [Host], type = [Type], source = [Source], message = [Message], [user] = [User], statusCode = [StatusCode], time = CONVERT(VARCHAR(50), [TimeUtc], 126) + 'Z' FROM [ELMAH_Error] error WHERE [Application] = @Application AND [TimeUtc] <= @FirstTimeUTC AND [Sequence] <= @FirstSequence ORDER BY [TimeUtc] DESC, [Sequence] DESC FOR XML AUTO
ELMAH_GetErrorXml
Create PROCEDURE[dbo].[ELMAH_GetErrorXml] ( @Application NVARCHAR(60), @ErrorId UNIQUEIDENTIFIER ) AS SET NOCOUNT ON SELECT [AllXml] FROM [ELMAH_Error] WHERE [ErrorId] = @ErrorId AND [Application] = @Application
ELMAH_LogError
Create PROCEDURE[dbo].[ELMAH_LogError] ( @ErrorId UNIQUEIDENTIFIER, @Application NVARCHAR(60), @Host NVARCHAR(30), @Type NVARCHAR(100), @Source NVARCHAR(60), @Message NVARCHAR(500), @User NVARCHAR(50), @AllXml NTEXT, @StatusCode INT, @TimeUtc DATETIME ) AS SET NOCOUNT ON INSERT INTO [ELMAH_Error] ( [ErrorId], [Application], [Host], [Type], [Source], [Message], [User], [AllXml], [StatusCode], [TimeUtc] ) VALUES ( @ErrorId, @Application, @Host, @Type, @Source, @Message, @User, @AllXml, @StatusCode, @TimeUtc )
Now again open web config file, add the following code inside in <configuration>.
</configuration> <elmah> <!--. If allowRemoteAccess value is set to 0, then the error log web page can only be viewed locally. If allowRemoteAccess attribute is set to 1 then the error log web page is enabled for both remote and local visitors.--> <!--add this--> <security allowRemoteAccess="0" /> <!-- DefaultConnection is the name of database connection string --> <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" /> <!--add this--> </elmah>
Note: You can view the error log web page through the url localhost:portno/elmah.axd like, localhost:55776/elmah.axd.
Take the reference of System.Linq.Expressions namespace and use an Expression<TDelegate> class to define an Expression. Expression<TDelegate> requires delegate type Func or Action.
For example, you can assign lambda expression to the isTeenAger variable of Func type delegate, as shown below:
Define Func delegate for an expression in C#
public class Student { public int StudentID { get; set; } public string StudentName { get; set; } public int Age { get; set; } } Func<Student, bool> isTeenAger = s => s.Age > 12 && s.Age < 20;
And now, you can convert the above Func type delegate into an Expression by wrapping Func delegate with Expression, as below:
Define Expression in C#
Expression<Func<Student, bool>> isTeenAgerExpr = s => s.Age > 12 && s.Age < 20;
In the same way, you can also wrap an Action<t> type delegate with Expression if you don't return a value from the delegate.
Define Expression in C#
Expression<Action<Student>> printStudentName = s => Console.WriteLine(s.StudentName);
You can invoke the delegate wrapped by an Expression the same way as a delegate, but first you need to compile it using the Compile() method. Compile() returns delegateof Func or Action type so that you can invoke it like a delegate.
Invoke Expression in C#
Expression<Func<Student, bool>> isTeenAgerExpr = s => s.Age > 12 && s.Age < 20; //compile Expression using Compile method to invoke it as Delegate Func<Student, bool> isTeenAger = isTeenAgerExpr.Compile(); //Invoke bool result = isTeenAger(new Student(){ StudentID = 1, StudentName = "Steve", Age = 20}); Output: false
Filtering out even numbers from an array is concise and efficient with LINQ.
int[] nums = { 1, 2, 3, 4, 5, 6 }; var evens = nums.Where(n => n % 2 == 0); Console.WriteLine(string.Join(", ", evens));
Explanation: The Where method filters the array based on the condition n % 2 == 0, leaving only the even numbers, which are then printed.