Monthly Archives: October 2013

C# getting correct user IP even if HTTP_X_FORWARDED_FOR contains multiple IP Addresses

HTTP_X_FORWARDED_FOR can return multiple IP Addresses, for example 32.122.54.21, 32.122.54.25, 32.122.65.23 following the general format of the field

X-Forwarded-For: client, proxy1, proxy2

Source: Wikipedia / X-Forwarded-For

My approach

public static string GetClientIp()
{
	string ip = string.Empty;

	ip = string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]) ? System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] : System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
	if (ip.Contains(","))
	{
		ip = ip.Split(',').First().Trim();
	}

	if (string.IsNullOrWhiteSpace(ip))
	{
		ip = "0.0.0.0";
	}
	
	return ip;
}
	

jQuery: Form validation with keyup examples

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
	<script>
	$(document).ready(function(){

		$("#txtFirstName").keyup(function() {
		
			 $('span.error').hide();

			var firstName = $(this).val();
			// allow '.','-' and space
			var firstNameRegex =/^[A-Za-z\s\'\-]*$/; //  /^[A-Za-z\s\'\-]*$/; //^[a-z\s]*$ ==== ^[A-Za-z\s][\.]{0,1}[A-Za-z\s]{0,}$"
			
			console.log(firstName);

			if(firstNameRegex.test(firstName)) 
			{
				$(this).after('<span class="error">Valid</span>');
			} 
			else 
			{
				$(this).after('<span class="error">Wrong!</span>');
			}
		});
	

		$("#txtEmail").keyup(function() {
		
			 $('span.error').hide();

			var email = $(this).val();
			var emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
			
			console.log(email);

			if(emailRegex.test(email)) 
			{
				$(this).after('<span class="error">Valid</span>');
			} 
			else 
			{
				$(this).after('<span class="error">Wrong!</span>');
			}
		});



		$("#btnSubmit").click(function() {

			$('span.error').hide();

			// note that toUpperCase() is used, not perfect solution
			var postalCode = ($("#txtPostalCode1").val() + $("#txtPostalCode2").val()).toUpperCase();
			var postalCodeRegex = /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]?\d[ABCEGHJKLMNPRSTVWXYZ]\d$/;
			var btnSubmit = $("#btnSubmit");

			console.log(postalCode);

			if(postalCodeRegex.test(postalCode)) 
			{
				$(btnSubmit).after('<span class="error">Valid</span>');
			} 
			else 
			{
				$(btnSubmit).after('<span class="error">Wrong!</span>');
			}
		});
	})
	</script>
</head>

<body>
		First name: 
		<input type="text" name="txtFirstName" id="txtFirstName" />
		<br />
		<br />
		Email: <input type="text" name="txtEmail" id="txtEmail" />
		<br />
		<br />
		Postal Code: 
		<input type="text" name="txtPostalCode1" id="txtPostalCode1" maxlength="3" style="width:30px; margin-right:10px;" />
		<input type="text" name="txtPostalCode2" id="txtPostalCode2" maxlength="3" style="width:30px; margin-right:10px;" />
		<input type="submit" value="Submit" id="btnSubmit" />
</body>
</html>

ASP.NET The length of the query string for this request exceeds the configured maxQueryStringLength value.

Similar problem happens described by error:

The request filtering module is configured to deny a request where the query string is too long.

Solution, step 1 in web.config:

<configuration>
   <system.web>
		<httpRuntime maxQueryStringLength="4096" />
	</system.web>
</configuration>

<!-- OR -->

<configuration>
   <system.webServer>
		<httpRuntime maxQueryStringLength="4096" />
	</system.webServer>
</configuration>

Solution, step 2 IIS:
In the Connections pane, go to the connection, site, application, or directory for which you want to modify your request filtering settings.
In the Home pane, double-click Request Filtering.

iis01

Click Edit Feature Settings… in the Actions pane.

iis02

Specify your options, and then click OK.

iis03

Source: Request Limits

C# Dapper – return single result

public static string GetImage(int restaurantId)
{
	using (SqlConnection conn = new SqlConnection(Common.ConnectionString))
	{
		conn.Open();
		const string query = "SELECT ImageURL FROM [Restaurant_Featured] WHERE RestaurantId = @RestaurantId";
		LEORestaurant_Featured featured = conn.Query<Restaurant_Featured>(query, new { RestaurantId = restaurantId }).SingleOrDefault();
		conn.Close();

		return featured != null && !string.IsNullOrWhiteSpace(featured.ImageURL) ? featured.ImageURL : string.Empty;
	}
}

SQL Server restore database – the backup set holds a backup of a database other than the existing database

I couldn’t use SQL Server Management Studio and restore database because it was crashing for some reason.
So, I had to use query

I’ve found helpful code on Stack Overflow and tried to use it.
Nothing was special about it until I got error ‘The backup set holds a backup of a database other than the existing ‘xx’ database.’

The solution was to use WITH REPLACE clause. For example

USE Master

RESTORE FILELISTONLY FROM DISK = 'C:\sqldata_backups\MyDB.bak'
RESTORE DATABASE LEOImport FROM DISK = 'C:\sqldata_backups\MyDB.bak'
WITH 
	MOVE 'MyDB' TO 'C:\sqldata\MyDB.mdf',
	MOVE 'MyDB_log' TO 'C:\sqldata\MyDB_log.ldf',
	REPLACE

To get logical names and locations of the files use following query

SELECT name, physical_name AS current_file_location
FROM sys.master_files 

MVC3 Webgrid sorting and paging

Helpful Webgrid walk through: MSDN Magazine
My challenge was that after filtering rendered collection, when clicked any sorting link I was getting full collection back.
Useful info

“When WebGrid renders the paging links, it reuses the page URL and attaches a query string parameter with the page number, such as http://localhost:27617/Product/DefaultPagingAndSorting?page=3”

Inspect with Firebug and you will see what’s passed to the backend.

Paging
webgrid_paging
Sorting
webgrid_sorting

All I had to do was modify Index action adding ‘page‘ and ‘sort‘ parameters.

public ActionResult Index(int page = 0, string sort = null)
{

	if (page == 0 && string.IsNullOrWhiteSpace(sort))
	{
		CurrentListing = new Listing();
	}
	else
	{
		TempData.Keep("CurrentListing");
	}