Support pre-flight OPTIONS requests in .Net WebAPI

A way to support the ‘OPTIONS’ pre-flight request in .net WebAPI is to by-pass this request with a default response and returning the required Headers.

Add the below code in your Global.asax.cs file under the Application_BeginRequest method:

protected void Application_BeginRequest()
{
	if (Request.HttpMethod == "OPTIONS")
	{
		HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
		HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, expiry, id, token, token-type");
		HttpContext.Current.Response.AddHeader("Access-Control-Allow‌​-Credentials", "true");
		HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
		HttpContext.Current.Response.End();
	}
}

So when you call the WebAPI with Javscript fetch/axios, the pre-flight request sent before the actual request would get the 200 status code.

The example above shows some sample custom headers and allowed methods that will be returned in Response Headers.

Delete Geckodriver temp folders using Powershell

Geckodriver is an executable that interacts with Firefox installed on the System to run automated tests by running the Firefox instance either fully or in ghost-mode.
Geckodriver creates profiles in the Windows temp folder that can be of huge size depending on the Profile created for the Firefox driver.
The folder name is of the format “rust_mozprofile*”.

The following Powershell script will delete such folders by searching for this string format under C:\windows\temp and also creates logs for the deleted folders.

$datestring = (Get-Date).ToString("s").Replace(":","-")

Start-Transcript C:\logs\Mozprofile_LogPurgeTranscript_$datestring.txt -NoClobber
get-childitem -path c:\windows\temp | where{$_.LastWriteTime -lt (get-date).AddDays(-30) -and $_.name -like "rust_mozprofile*" -and $_.psiscontainer -eq $true} |Sort-Object lastwritetime -Descending| select -last 100 |% {remove-item -Recurse $_.fullname -force -Verbose -Confirm:$false}
Stop-Transcript

This PowerShell script can also be used to generally search for folders and matching a string a delete them.

Enable CORS in .Net Core WebAPI

It is a common scenario where a React front-end SPA is calling a .Net Core WebAPI to fetch data. In this case, suppose both Applications are using their respective domains shown below:

React App => http://myfrontend.com
API=> http://myapi.com

CORS (Cross-Origin Resource Sharing) is a standard that works by adding HTTP headers that allow servers to describe the set of origins that are permitted to fetch information using a web browser and the kind of requests that are allowed.
For the API to allow the React App to fetch the data, it has to allow the Origin of the React App. This is a common CORS problem. So if you’re using, say axios or Fetch, to fetch data from the .Net Core WebAPI, it will only succeed if the API allows the domain http://myfrontend.com to call itself.

Below I’ve used the technique of CORS with named policy and middleware:

public class Startup
{
	public Startup(IConfiguration configuration)
	{
		Configuration = configuration;
	}
	readonly string MyAllowedOrigins = "_myAllowedOrigins";
	public IConfiguration Configuration { get; }
	public IContainer ApplicationContainer { get; private set; }
	// This method gets called by the runtime. Use this method to add services to the container.
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddControllers();
		services.AddCors(options =>
		{
			options.AddPolicy(MyAllowedOrigins,
			builder =>
			{
				//Allowing both the localhost and hosted domains.
				builder.WithOrigins("http://localhost:3000",
									"http://www.myfrontend.com");
			});
		});
	}
	
	//Apply CORS policies to all endpoints via CORS Middleware:
	// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
	public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
	{
		//Omitted code
		app.UseCors(MyAllowedOrigins);
		app.UseEndpoints(endpoints =>
		{
			endpoints.MapControllers();
		});
		//Omitted code
	}
}

The example above is how you apply CORS policy globally to all endpoints in your API. You can also use the [EnableCors(“Policy String”)] attribute on your controllers/page-model/action method.

e.g. Applying CORS on Action method:

[EnableCors("_myAllowedOrigins")]
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
	return new string[] { "test1", "test2" };
}

It is recommended to enable CORS either locally or globally and not combine the two approaches.

We can also expose the allowed Headers and http methods the following way:

public void ConfigureServices(IServiceCollection services)
{
	services.AddControllers();
	services.AddCors(options =>
	{
		options.AddPolicy(MyAllowSpecificOrigins,
		builder =>
		{
			builder.WithOrigins("http://myfrontend.com", "http://localhost:3000")
			.WithHeaders("token")
			.WithMethods("OPTIONS", "GET", "POST");
		});
	});
}

You can also allow credentials to be passed to the WebAPI from the Client by chaining the .AllowCredentials method.

Pre-flight requests for OPTIONS method call fails with Windows authentication and gives 401 Unauthorized. This can be worked around by enabling both Windows and Anonymous authentication.

If you are using Windows Authentication in the case of an Intranet Application and also enabled Anonymous Authentication for allowing OPTIONS pre-flight request, then make sure to use [Authorize] and [AllowAnonymous] attributes to the respective endpoints where required. Without using [Authorize], the name of the user is returned
null with context.HttpContext.User.Identity.Name where context is the ActionExecutingContext object. These attributes can be used on Controllers or Actions as required.
Also, make sure to setup the middleware in the correct order for using with UseCors, UseAuthentication and UseAuthorization in the Startup.cs file Configuration.

How to call a Stored Procedure from Classic ASP

ASP is a program based on Microsoft Technologies that runs inside a web server.

Below is the method used for calling a Stored Procedure in MSSQLSERVER using classic ASP scripting.

The variable SystemDSN holds the value of the Data Source Name that is configured using Odbcad.exe under the SysWow64 folder on the Server. Select the required driver for SQL Server for the DSN configuration to connect to your database.

Set cn = Server.CreateObject("ADODB.Connection")
cn.Open SystemDSN
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cn
cmd.CommandText = "usp_GetJSON"
cmd.CommandType = adCmdStoredProc

cmd.Parameters.Append(cmd.CreateParameter("@Ticket_Code",adInteger,adParamInput,100, Request.QueryString("inp_ticket_id")))
cmd.Parameters.Append(cmd.CreateParameter("@Username",adVarchar,adParamInput,100000,user))
cmd.Parameters.Append(cmd.CreateParameter("@OperatorID",adVarchar,adParamInput,100000,oprID))

cmd.Parameters.Append(cmd.CreateParameter("@ReturnJson", adVarchar, adParamOutput,100000))
cmd.Execute

'show alert in case of failure.
ReturnValue = cmd.Parameters("@ReturnJson").Value
if ReturnValue <> " " then
  jsonObject = ReturnValue
  'set the flag as 1 to ensure that JSON has been returned from SP to be used later.
  flag= "1"

end if

The above example shows the SP takes 3 input parameters and 1 output parameter. The SP returns a jsonObject assigned to the ReturnValue.

The ADO Connection Object is used to create an open connection to a data source which lets you access and manipulate a database. The ADO Command object is used to execute a single query against a database using which you can perform CRUD operations.

The json can be generated in the SP using the “FOR JSON PATH” feature for SQL Server. However, json is used just for this example. The return value can be anything as per your requirement.

Global Exception Handling and Logging in aspnet core webapi

Create a Model for your Error details as below:

public class ErrorDetails
{
	public int StatusCode { get; set; }
	public string Message { get; set; }


	public override string ToString()
	{
		return JsonConvert.SerializeObject(this); //JsonConvert is part of Newtonsoft.Json package.
	}
}

Create the Exception Factory which will handle Exceptions globally in your Api:

public static class ExceptionFactory
{ 
    public static void ConfigureExceptionHandler(this IApplicationBuilder app, int StatusCode = 0, string message = "")
    {
        app.UseExceptionHandler(appError =>
        {
            appError.Run(async context =>
            {
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                context.Response.ContentType = "application/json";
                
                var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                if (contextFeature != null)
                {
                    LogTraceFactory.LogError($"Something went wrong: {contextFeature.Error}");

                    await context.Response.WriteAsync(new ErrorDetails()
                    {
                        StatusCode = context.Response.StatusCode,
                        Message = "Internal Server Error."
                    }.ToString());
                }
            });
        });
    }
}

Register Exception handling in your Api:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	app.ConfigureExceptionHandler();
	.....
}

Also, you can return the error details in your Action Controllers as below:

[HttpGet]
[Route("product/getproductdetails")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public IActionResult GetproductDetails([FromQuery]int productId)
{
	LeadsProduct lead = null;
	if (productId == 0)
	{
		LogTraceFactory.LogError($"Incorrect parameters, productId: {productId}");
		return BadRequest(new ErrorDetails { StatusCode = Convert.ToInt32(HttpStatusCode.BadRequest), Message = $"Missing parameters, productId: {productId} for product Leads." });
	}

	lead = leadService.FetchProductDetails(productId);

	if (lead == null)
	{
		LogTraceFactory.LogError($"product Leads Not Found for productId: {productId}");
		return NotFound(new ErrorDetails { StatusCode = Convert.ToInt32(HttpStatusCode.NotFound), Message = $"product Leads not found for productId {productId}." });
	}

	return Ok(lead);
}

The example above uses the nlog package in the .net core Web Api. You can create LogTraceFactory class as below:

public static class LogTraceFactory
{
	private static ILogger logger = LogManager.GetCurrentClassLogger();

	public static void LogDebug(string message)
	{
		logger.Debug(message);
	}

	public static void LogError(string message)
	{
		logger.Error(message);
	}

	public static void LogInfo(string message)
	{
		logger.Info(message);
	}

	public static void LogWarn(string message)
	{
		logger.Warn(message);
	}
}

Configure nlog package as below in the nlog.config file:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Trace"
      internalLogFile="C:\internal_logs\internallog.txt">

  <targets>
    <target name="logfile" xsi:type="File"
            fileName="C:\ProjectLogs\${shortdate}_logfile.txt"
            layout="${longdate} ${level:uppercase=true} ${message}"/>
  </targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="logfile" />
  </rules>
</nlog>

You can modify the above configuration as required. As part of the clean architecture, it is better to setup the ExceptionFactory and LogTraceFactory in the Common Layer of your Solution.


Omg! Now you can earn a six figure income. Click here to know how.

How to serialize data using translator C# .net core webapi

Suppose you’re trying to fetch user data from your database using ado.net in you .net core webapi. You have a SQLHelper class that calls a Stored Procedure and returns data that requires to be converted to a DTO object with pre-defined properties in C#.

The SQLHelper class will have the following method to call your Stored Procedure:

public static TData ExtecuteProcedureReturnData<TData>(string connString, string procName,
	Func<SqlDataReader, TData> translator,
	params SqlParameter[] parameters)
{
	using (var sqlConnection = new SqlConnection(connString))
	{
		using (var sqlCommand = sqlConnection.CreateCommand())
		{
			sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
			sqlCommand.CommandText = procName;
			if (parameters != null)
			{
				sqlCommand.Parameters.AddRange(parameters);
			}
			sqlConnection.Open();
			using (var reader = sqlCommand.ExecuteReader())
			{
				TData elements;
				try
				{
					elements = translator(reader);
				}
				finally
				{
					while (reader.NextResult())
					{ }
				}
				return elements;
			}
		}
	}
}

What is a Translator?

A translator is a class like a DTO in C# which will serialize your data returned from the Stored Procedure into it’s properties.
This will be returned as a json object by your WebApi to your Client front-end.

You can create a Translators folder in your .net core WebApi Project to have all such classes in one place.

An example Translator is as shown below:

public static class UserTranslator
{
	public static User TranslateAsUser(this SqlDataReader reader)
	{
		if (!reader.HasRows)
			return null;
		reader.Read();

		var item = new User();

		if (reader.IsColumnExists("Username"))
			item.Username = SqlHelper.GetNullableString(reader, "Username");

		if (reader.IsColumnExists("FullName"))
			item.FullName = SqlHelper.GetNullableString(reader, "FullName");
			
		if (reader.IsColumnExists("RoleName"))
                item.RoleName = SqlHelper.GetNullableString(reader, "RoleName");

		if (reader.IsColumnExists("Email"))
			item.Email = SqlHelper.GetNullableString(reader, "Email");

		return item;
	}
}

In the above example, you data will have the following columns as Username, FullName and Email. It only returns one row and not a list.

For returning a list:

public static List<User> TranslateAsUsersList(this SqlDataReader reader)
{
	var list = new List<User>();
	while (reader.Read())
	{
		list.Add(TranslateAsUser(reader, true));
	}
	return list;
}

Make sure your reader.Read() method is not called twice.

The DTO for user is as follows:

public class User
{
	public string Username { get; set; }
	public string FullName { get; set; }
	public string RoleName { get; set; }
	public string Email { get; set; }
}

Now, you need to call your Stored Procedure from your Repository:

public User getUserDetails(string UserName)
{
	string connString = CommonUtil.ConnectionString;
	SqlParameter[] param =
	{
		new SqlParameter("@Username", UserName)
	};

	User user = SqlHelper.ExtecuteProcedureReturnData<User>(
		connString,
		"GetUserDetailsFromDB",
		r => r.TranslateAsUser(), //call TranslateAsUsersList if List of Users is required and return List<User>
		param
		);

	return user;
}

Assuming, you’re using the Repository pattern in your WebApi Data Layer. Else, you can call the above method however your Project structure works.

I’ve written another post on multiple ways to fetch data for calling StoredProcedure in your WebApi for your SQLHelper class.

Write C# method that returns DataSet from Stored Procedure

Suppose you are writing a Helper class in your .Net Project that uses ADO.Net in the Data Layer. And you need to call Stored Procedures a lot. Writing a generic Helper method that takes in an Array of SqlParameters can be used so that you don’t have re-write the same code of calling the Stored Procedure again and again.

Below is the code that I’ve used as a general approach to call Stored Procedure and return DataSet:

public static DataSet ExecuteProcedureReturnDataSet(string connString, string procName,
            params SqlParameter[] paramters)
{
	DataSet result = null;
	using (var sqlConnection = new SqlConnection(connString))
	{
		using (var command = sqlConnection.CreateCommand())
		{
			using (SqlDataAdapter sda = new SqlDataAdapter(command))
			{
				command.CommandType = System.Data.CommandType.StoredProcedure;
				command.CommandText = procName;
				if (paramters != null)
				{
					command.Parameters.AddRange(paramters);
				}
				result = new DataSet();
				sda.Fill(result);
			}
		}
	}
	return result;
}

Another way to call Stored Procedure would be to return a single value from the Stored Procedure like a string. You can use the below method to return only a String:

public static string ExecuteProcedureReturnString(string connString, string procName,
            params SqlParameter[] paramters)
{
	string result = "";
	using (var sqlConnection = new SqlConnection(connString))
	{
		using (var command = sqlConnection.CreateCommand())
		{
			command.CommandType = System.Data.CommandType.StoredProcedure;
			command.CommandText = procName;
			if (paramters != null)
			{
				command.Parameters.AddRange(paramters);
			}
			sqlConnection.Open();
			var ret = command.ExecuteScalar();
			if (ret != null)
				result = Convert.ToString(ret);
		}
	}
	return result;
}

Example of SqlParameter array to be passed to the above methods can be as follows:

SqlParameter[] params =
{
	new SqlParameter("@name", name),
	new SqlParameter("@year", year)
};

How to read connection strings stored in appsettings file C#

This post is based on a setup of an asp.net core application. Configuration is read in the Startup class upon the Application startup. The Configure method in this class calls the ApiBootstrapper to check whether the connection string for Dev or Production is required.
This can be further used to call the Stored Procedures or query tables using ADO.Net.

Appsettings.json file is the asp.net core config file. This file contains the Connection Strings is as shown below:

{
	"configSetting": {
		"ConnectionStrings": {
			"ProdConnection": "Data Source=ServerName;Initial Catalog=DBProd;UID=username;PWD=password;",
			"DevConnection": "Data Source=ServerName;Initial Catalog=DBDev;UID=username;PWD=password;"
		},
		"Parameters": {
			"IsProduction": true
			"IsDev": false
		}
	}
}
public class Startup
{
	public Startup(IConfiguration configuration)
	{
		Configuration = configuration;
	}
	
	public IConfiguration Configuration { get; }
	
	public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
	{
		////
	
	
		ApiBootstrapper.Initialize(Configuration);
	}
	
}

Below is the code for ApiBootstrapper class:

public class ApiBootstrapper
{
	
	public static void Initialize(IConfiguration configuration)
	{
		CommonUtil.IsProduction = configuration.GetSection(ConfigKeys.configSetting.ToString()).GetSection(ConfigKeys.Log.ToString()).Value.ToString();
		if (Convert.ToBoolean(CommonUtil.IsProduction))
		{
			CommonUtil.ConnectionString = configuration.GetSection("configSetting").GetSection("ConnectionStrings").GetSection("ProdConnection").Value.ToString();
		}
	}
}

The above example shows how we can store Connection Strings for different environments like Dev and Prod and read it based on Config file settings.

How to clean uninstall Xcode on Mac

Many times it happens that you update your MacOS and then some new update comes up for the Xcode version and there is a backwards compatibility issue. Then you go to the App Store on your Mac to update the Xcode and Bam! You end up wasting hours because the installation gets stuck. It keeps showing installing for hours. If you force shutdown your MacOS and restart, then again the same story.

This time it happened with me again after I updated MacOS Catalina and installation of Xcode 11.3 just doesn’t end. Stopping in App Store doesn’t work.

Another way is, going to the Launchpad and holding down the alt/option key till all the icons start to jiggle. Then click on the x icon and you’ll be prompted to confirm to delete the Xcode App. Well, this also didn’t work for me. Then restart your Mac to move to the next steps.

Go to the Applications folder and find the Xcode App, right-click on it and move it to Trash/Bin. Empty the Trash/Bin.

For newer versions of Xcode, this step should be sufficient. You can go ahead and re-install Xcode from the App Store.

Removing from the Terminal

You need to run the following command in order to completely remove Xcode:

sudo /Developer/Library/uninstall-devtools --mode=all

The above command requires the admin password for sudo. If you get the error that the above command not found, then it probably doesn’t work for the newer versions of Xcode.

You might need to consider backing up the data in case you have Projects in the Developer folder and certain preferences to preserve in case you’re reinstalling. Back-up some of these files/folders before deleting anything:

~/Library/Developer/Xcode/UserData/CodeSnippets
~/Library/Developer/Xcode/UserData/FontAndColorThemes
~/Library/Developer/Xcode/UserData/KeyBindings
~/Library/Developer/Xcode/Templates
~/Library/Preferences/com.apple.dt.Xcode.plist
~/Library/MobileDevice/Provisioning Profiles

The following folders are cleared with complete uninstallation of Xcode:

  • /Applications/Xcode.app
  • /Library/Preferences/com.apple.dt.Xcode.plist
  • ~/Library/Preferences/com.apple.dt.Xcode.plist
  • ~/Library/Caches/com.apple.dt.Xcode
  • ~/Library/Application Support/Xcode
  • ~/Library/Developer/Xcode
  • ~/Library/Developer/CoreSimulator
  • /System/Library/Receipts/com.apple.pkg.XcodeExtensionSupport.bom
  • /System/Library/Receipts/com.apple.pkg.XcodeExtensionSupport.plist
  • /System/Library/Receipts/com.apple.pkg.XcodeSystemResources.bom
  • /System/Library/Receipts/com.apple.pkg.XcodeSystemResources.plist
  • /private/var/db/receipts/com.apple.pkg.Xcode.bom

Remove the files at ~/Library/Caches/com.apple.dt.Xcode is basically clearing the cache. You can delete anything under /Library/Developer/ directory, such as CommandLineTools and CoreSimulator, except PrivateFrameworks subfolder. This might cause your newly installed Xcode to crash until you put it back.

Share your experience on what worked for you to make this post better.

Join Armoney for best Cryptocurrency trading experience. Trade from anywhere, anytime!

How to Count number of e-mails in mailbox using PowerShell

First, you need to access the mailbox on the Microsoft Exchange Server and then get the mailbox statistics for the count of e-mails. The credentials you use should have admin access on the Server to be able to access the mailbox.

The following script uses some credentials stored in a file on the machine where the script is running and connects to a Session on the Microsoft Exchange Server:

$un = “admin@somedomain.com”
$Pass = cat “C:\Data\Securestring.txt” | ConvertTo-SecureString
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Un, $Pass

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://{servername}/PowerShell/ -Authentication Kerberos -Credential $Credentials

Import-PSSession $Session -DisableNameChecking

$data=Get-MailboxFolderStatistics -Identity "somemail@somedomain.com" -FolderScope inbox | ?{$_.folderpath -eq "/inbox"} | select ItemsInFolder 

Write-Host $data.ItemsInFolder

You can further use this data item to mail it to the Admins for Operations purpose.

To know how to send e-mail in PowerShell, check out this post here.