Chrome Developer Tools Productivity Tips

No Comments

Most Useful Shortcuts
Ctrl Shift I – Open developer tools.
Ctrl Shift P – Search within file. Displays all functions within a file.
Ctrl P – show js files. Type to search.
Ctrl Shift C – inspect element
Esc – toggle console
Ctrl F – find inside a file
Ctrl Shift F – find across all sources

To enable text editing directly in a browser:
document.body.contentEditable = true;

To time something: console.time(“my action”); … console.timeEnd(“my action”)

Snippets – run custom JavaScript code and run it anwhere you want. https://bgrins.github.io/devtools-snippets/

To disable cache – Network tab – disable cache (while DevTools is open).

Add timestamp to events displayed in console – Settings – General – Console – Show timestamps.

Enabling awesome dark theme:
Go to chrome://flags – Enable Developer Tools Experiments.
Open Chrome Dev Tools. – Settings – Experiments – allow custom UIthemes
Install a DevTools Theme. Here’s one.

A cool video about the above and much more – Chrome Developer Tools Deep Dive by Shay Friedman

Categories: Web

Free Options to Protect a WordPress Site

No Comments
  • Do not use username “admin” – when someone tries to brute-force into your site, this will likely be the first username they try.
    Keep your WordPress and plugins up to date.
  • Use a password manager to store your passwords. This will allow you to use strong passwords for your site (and anything else) without committing your memory to remembering all of the combinations special characters, letters and numbers.
  • Akismet – a very effective option to detect and block spam comments from your blog.
  • Wordfence (free/paid) – a free version allows to scan your source code, themes and plugins; set up limits on login attempts; sent email notifications when somebody logs in to your site or enters invalid credentials. If the number of users who can login to you site is relatively small, I recommend immediately locking out the users who try to log in with an invalid name, which is an excellent option to defend against brute-force attacks.
    A paid version allows to set up two-factor authentication, country-blocking, advanced spam scan options.
  • IQ Block Country (free) – you can combine it with the Wordfence to get additional protection for country blocking if you don’t want to pay Premium for Wordfence. IQ Block Country allows to block certain countries (determined by IP) from logging to either your frontend or backend pages.

There is a potential that Wordfence and IQ Block country may conflict with each other; I have used both plugins without experiencing any conflicts.
When considering country blocking, you may want to check your Spam folder to see where most of your spam comes from; or if you already use Wordfence – it can tell from which countries most of the invalid logins orginate. Use this information to lock your back-end or front-end. I found country blocking surprisingly effective against spam.
Read More…

Categories: Security Tags: Tags:

Improving Visual Studio Performance with RAM disk and Second SSD

No Comments

One of the best way to improve Visual Studio performance is to replace your HDD with SSD. However, for various reasons it may not always an option. Here are a few other hardware-related suggestions that may help your Visual Studio experience:

  • If you have enough RAM, create a RAM disk (I use freeware from SoftPerfect ). Set your web.config to use it as a temp compilation directory:
     <compilation tempDirectory="R:\TempAspFolderOnRamDisk">
    

    While you are there, you can experiment with batch parameter. It is used to control whether the initial page request will continue to compile additional files in the same directory before completing the original request. I prefer to set it to false.

  • If you have an ability to add a second SSD, you may want to move all your source code to it. However, it may mean you have to change the configuration on your machine to make it work on a different drive/folder. To avoid this configuration headache, instead create a symbolic link between your original source code directory, and the new one on the SSD drive:

    mklink /D "C:\originalSourceCodeDirectory" R:\DirectoryOnSSD
    

    You have to delete or rename the originalSourceCodeDirectory prior to running mklink command.

  • Move your bin/obj folders to RamDisk. Use symbolic links to avoid configuration problems. This did not seem to have any noticeable effect on my configuration, but your mileage may vary.
  • Use some caching software like PrimoCache. It allows to cache data either to your RAM or an additional SSD.

The most beneficial of these techniques for me was moving source code to SSD.

Categories: Performance Tags: Tags:

Passing custom objects to FluentValidation

No Comments

This is a guide for passing custom objects to Fluent Validators. This can be helpful for more complex validation scenarios.

Here’s an example of what we want to achieve:

public class OurModelValidator: AbstractValidator<OurMVCViewModel>
{
public OurModelValidator(OurClassWeWantToPassToValidator ourClassWeWantToPassToValidator)
{
if (ourClassWeWantToPassToValidator.SomeCondition)
{
RuleFor(m => m.PropertyA).NotEmpty();
}
else
{
RuleFor(m => m.PropertyB).NotEmpty();
}
}
}

In order to achieve this, we need to make some changes to the FluentValidationModelValidatorProvider class by overriding its CreateValidator method:

public class OurCustomFluentModelValidatorProvider : FluentValidationModelValidatorProvider
{

protected override IValidator CreateValidator(ModelMetadata metadata, ControllerContext context)
{
var type = this.IsValidatingProperty(metadata) ? metadata.ContainerType : metadata.ModelType;
return GetOurModelValidator(type) ?? this.ValidatorFactory.GetValidator(type);
}

private IValidator GetOurModelValidator(Type modelType)
{
if (modelType == typeof(OurClassWeWantToPassToValidator))
{
var ourClassWeWantToPassToValidator = new OurClassWeWantToPassToValidator();
return new OurModelValidator(ourClassWeWantToPassToValidator);
}

return null;
}
}

Since we want FluentValidation to handle all situation when OurModelValidator is not applicable, we use built-in ValidatorFactory to return default Validator when validating anything but OurMVCViewModel.

And the last step is to register our new provider:

ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
ModelValidatorProviders.Providers.Add(new DataErrorInfoModelValidatorProvider());
ModelValidatorProviders.Providers.Add(new ClientDataTypeModelValidatorProvider());
ModelValidatorProviders.Providers.Add(new OurCustomFluentModelValidatorProvider());
Categories: MVC, Web Tags: Tags:

FluentValidation Client-Side Custom Validation with MVC

5 Comments

FluentValidation is “A small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects.” It is quite awesome. However, the provided client-side validation is limited:  “any rules defined using a condition (with When/Unless), custom validators, or calls to Must will not run on the client side.” Below is some my first take on using FluentValidation on both server and client-side.

First, you need to install the nuget package. In our case, it is FluentValidation.MVC4.

We needed to make a certain property required, but only when some other property is true. To achieve this on client-side (server-side is trivial), we added these:

	public class RequiredIfClientSideValidator : PropertyValidator
	{
		public string DependentProperty { get; set; }
		public object TargetValue { get; set; }

		public RequiredIfClientSideValidator(string errorMessage, string dependentProperty, object targetValue)
			: base(errorMessage)
		{
			this.DependentProperty = dependentProperty;
			this.TargetValue = targetValue;
		}

		protected override bool IsValid(PropertyValidatorContext context)
		{
			//This is not a server side validation rule. So, should not effect at the server side.  
			return true;
		}
	}

And this

	public class RequiredIfClientSideFluentPropertyValidator : FluentValidationPropertyValidator
	{
		private RequiredIfClientSideValidator RequiredIfClientSideValidator
		{
			get { return (RequiredIfClientSideValidator)Validator; }
		}

		public RequiredIfClientSideFluentPropertyValidator(ModelMetadata metadata,
													   ControllerContext controllerContext,
													   PropertyRule propertyDescription,
													   IPropertyValidator validator)
			: base(metadata, controllerContext, propertyDescription, validator)
		{
			ShouldValidate = false;
		}

		public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
		{
			if (!ShouldGenerateClientSideRules()) yield break;

			var formatter = new MessageFormatter().AppendPropertyName(Rule.GetDisplayName());
			string message = formatter.BuildMessage(RequiredIfClientSideValidator.ErrorMessageSource.GetString());

			var rule = new ModelClientValidationRule()
			{
				ValidationType = "requiredif",
				ErrorMessage = message
			};

			string depProp = BuildDependentPropertyId(Metadata, ControllerContext as ViewContext);
			// find the value on the control we depend on;
			// if it's a bool, format it javascript style 
			// (the default is True or False!)
			string targetValue = (RequiredIfClientSideValidator.TargetValue ?? "").ToString();
			if (RequiredIfClientSideValidator.TargetValue.GetType() == typeof(bool))
				targetValue = targetValue.ToLower();

			rule.ValidationParameters.Add("dependentproperty", depProp);
			rule.ValidationParameters.Add("targetvalue", targetValue);

			yield return rule;
		}

		private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
		{
			// build the ID of the property
			string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(RequiredIfClientSideValidator.DependentProperty);
			// unfortunately this will have the name of the current field appended to the beginning,
			// because the TemplateInfo's context has had this fieldname appended to it. Instead, we
			// want to get the context as though it was one level higher (i.e. outside the current property,
			// which is the containing object (our Person), and hence the same level as the dependent property.
			var thisField = metadata.PropertyName + "_";
			if (depProp.StartsWith(thisField))
				// strip it off again
				depProp = depProp.Substring(thisField.Length);
			return depProp;
		}
	}

Additionally, we introduced a validator for simple client-side validation (ClientSideValidator) where you just need to pass an error message to your JavaScript validation.

public class ClientSideValidator : PropertyValidator
	{
		public string JavascriptValidationAdapterName { get; set; }

		public ClientSideValidator(string errorMessage, string javascriptValidationFunctionName)
			: base(errorMessage)
		{
			JavascriptValidationAdapterName = javascriptValidationFunctionName;
		}

		protected override bool IsValid(PropertyValidatorContext context)
		{
			//This is not a server side validation rule. So, should not effect at the server side.  
			return true;
		}
	}

And an accompanying class:

	
	public class ClientSideFluentValidator : FluentValidationPropertyValidator
	{
		private ClientSideValidator ClientSideValidator
		{
			get { return (ClientSideValidator)Validator; }
		}

		public ClientSideFluentValidator(ModelMetadata metadata,
			ControllerContext controllerContext,
			PropertyRule propertyDescription,
			IPropertyValidator validator)
			: base(metadata, controllerContext, propertyDescription, validator)
		{
			ShouldValidate = false;
		}

		public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
		{
			if (!ShouldGenerateClientSideRules()) yield break;

			var formatter = new MessageFormatter().AppendPropertyName(Rule.GetDisplayName());
			string message = formatter.BuildMessage(ClientSideValidator.ErrorMessageSource.GetString());

			var rule = new ModelClientValidationRule()
			{
				ValidationType = ClientSideValidator.JavascriptValidationAdapterName,
				ErrorMessage = message
			};
			
			yield return rule;
		}
	}

Register your custom validators in Global.asax.cs:

FluentValidationModelValidationFactory requiredIfClientSideValidationFactory =
				(metadata, context, rule, validator) =>
					new RequiredIfClientSideFluentPropertyValidator(metadata, context, rule, validator);
			
			FluentValidationModelValidationFactory clientSideValidationFactory =
				(metadata, context, rule, validator) =>
					new ClientSideFluentValidator(metadata, context, rule, validator);
			
			FluentValidationModelValidatorProvider.Configure(provider =>
			{
				provider.Add(typeof(RequiredIfClientSideValidator), requiredIfClientSideValidationFactory);
				provider.Add(typeof(ClientSideValidator), clientSideValidationFactory);
			});

Don’t forget to add the JavaScript part:
For requiredif validation:

$.validator.addMethod('requiredif',
    function (value, element, parameters) {
    	var id = '#' + parameters['dependentproperty'];

    	// get the target value (as a string, 
    	// as that's what actual value will be)
    	var targetvalue = parameters['targetvalue'];
    	targetvalue =
          (targetvalue == null ? '' : targetvalue).toString();

    	// get the actual value of the target control
    	// note - this probably needs to cater for more 
    	// control types, e.g. radios
    	var control = $(id);
    	var controltype = control.attr('type');
    	var actualvalue =
            controltype === 'checkbox' ?
            control.attr('checked').toString() :
            control.val();

    	// if the condition is true, reuse the existing 
    	// required field validator functionality
    	if (targetvalue.toLowerCase() === actualvalue.toLowerCase())
    		return $.validator.methods.required.call(
              this, value, element, parameters);

    	return true;
    }
);

$.validator.unobtrusive.adapters.add(
    'requiredif',
    ['dependentproperty', 'targetvalue'],
    function (options) {
    	options.rules['requiredif'] = {
    		dependentproperty: options.params['dependentproperty'],
    		targetvalue: options.params['targetvalue']
    	};
    	options.messages['requiredif'] = options.message;
    });

And for propertycvalidator:

$.validator.addMethod('propertycvalidator', function (value, element, parameters) {
			//put your client-side validation logic here
			return true;
		});

		$.validator.unobtrusive.adapters.addBool('propertycvalidator');

And, now we are ready to create our model validator:

		public class MyValidator()
		{
			//Make SomeProperty required. It will be validated on server and client side.
			RuleFor(m => m.SomeProperty)
				.NotEmpty().WithMessage("Some Property is required");
			//SomeOtherProperty will be validated on server side - it is required when PropertyB is true.
			//Client side validation is done by using RequiredIfClientSideValidator and passing dependent property 
			//name to unubtrusive JavaScript validation
			RuleFor(m => m.SomeOtherProperty)
				.NotNull()
				.WithMessage("Some other property is required")
				.When(model => model.PropertyB)
				.SetValidator(new RequiredIfClientSideValidator(
					"Some other property is required",
					"PropertyB",
					true));

			//this will get validated on client side only
			RuleFor(m => m.PropertyC)				
				.SetValidator(
					new ClientSideValidator(
						"Error message",
						"propertycvalidator")); // must be lower case
		}

The last part is adding the attribute to your model:
[Validator(typeof(MyValidator))]
public class YourModel
{
}

Categories: MVC, Web Tags: Tags:

Migrating Windows Server 2003 to 2012

13 Comments

This is an overview of my effort to upgrade some of our old 2003 servers to Windows Server 2012. It is quite possible there are better ways to accomplish this, as I’m just a developer and server upgrade is not something I do… well it was the first time I did it.

Migrating IIS 6.0 to 8.5

First, I needed to migrate IIS applications, app pools and app pools account. In order to automate this as much as possible, I installed Microsoft Web Platform installer on 2003 and Web Deploy 3.5 (The Web Deployment Tool). I used this guide http://www.iis.net/learn/publish/using-web-deploy/synchronize-iis-60-web-sites to help me.

Create backup on IIS6: iisback /backup /b PreWebDeploy

View dependencies on IIS 6: msdeploy -verb:getDependencies -source:metakey=lm/w3svc/1

Create package on IIS 6:

“C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe” -verb:sync  -source:metakey=lm/w3svc/1 -dest:package=C:\YourExportedPackage.zip,encryptPassword=YourPassword  -enableLink:AppPoolExtension

The password is required since we are exporting App Pools and the identities they use (by specifying enableLink:AppPoolExtension).

Run whatif analysis on IIS 2012:

“C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe” -verb:sync -source:package=c:\YourPackage.zip,encryptPassword=YourPassword -dest:metakey=lm/w3svc/1 -whatif > msdeploysync.log  -enableLink:AppPoolExtension

This will run what-if analysis without actually migrating anything. Check the log and install needed dependencies. Once all dependencies are installed, run the actual migration:

“C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe” -verb:sync -source:package=C:\YourPackage.zip,encryptPassword=YourPassword -dest:metakey=lm/w3svc/1 -enableLink:AppPoolExtension

 Another way (this does not copy the content, so you have to copy the folders with sites contents):
[appcmd seems to be available only starting with IIS7. Thanks to Nick for the correction.]
Run On Source:

C:\Windows\System32\inetsrv\appcmd list apppool /config /xml > C:\ apppools.xml

C:\Windows\System32\inetsrv\appcmd list site /config /xml > C: \sites.xml

Run On Destination:

C:\Windows\System32\inetsrv\appcmd add apppool /in < C:\apppools.xml

C:\Windows\System32\inetsrv\appcmd add site /in < C: \sites.xml

Migrating Shares and related permissions

First, create all of the folders for the shares. Then export the whole folder from the registry: Created registry export for the whole folder from 2003: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ LanmanServer \ Shares

Restore it on the destination server. This almost takes care of all the shares, except for NTFS permissions.

To copy NTFS permissions run on source:

Icacls C:\YourFolderThatNeedsNtfsPermissionesCopied  /save ExportedFileWithPermissions.txt /t

Run on destination:

Icacls C:\ /restore ExportedFileWithPermissions.txt

 

Migrate Users and Groups

First, install Windows Server Migration. Then use SmigDeploy to migrate users and groups.

Run on Destination (some parameters may be different for other configurations. Google SmigDeploy):

SmigDeploy.exe /package /architecture X86 /os WS03 /path C:\userMigrationTool

Go to Source server and run from userMigrationTool folder (created in a previous step). This will register SmigDeploy on source.

.\Smigdeploy.exe

Run on source:

Export-SmigServerSetting -User All -Group -Path C:\YourMIgrationFolder -Verbose

It’ll ask you a password. Pick one.

Run on destination:

Import-SmigServerSetting -Group -Path C:\YourMigrationFolder -Verbose

 

COM

Since I needed to migrate some COM’s, I had to add a feature COM+ Network Access to enable COM.

Tasks

Open Task Scheduler on destination.

Go to Action – Connect to another Computer. Connect to your source server.

Export the tasks to a temporary location as xml files. I didn’t see a way to export them all at once, so I did it one by one.

Open Task Scheduler on your destination again. Import the tasks.

It may pop up a message saying the account that you used to set up the task needs “Log on as batch job” privileges. In that case, follow a few more steps:

Run secpol.msc /s

Select “Local Policies” in MSC snap in

 Select “User Rights Assignment”

 Right click on “Log on as batch job” and select Properties

Click “Add User or Group”, and include the relevant user.

Categories: Uncategorized Tags: Tags:

TFS Build Error SB4062 Microsoft.TeamFoundation.Build.Tasks.dll not found

No Comments

I encountered an issue where a local build would fail on my machine, while succeeding on the other. I used Visual Studio 2010 for the build. This is the error message:

Error SB4062: The “Microsoft.TeamFoundation.Build.Tasks.BuildStep” task could not be loaded from the assembly C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.dll.

The solution was to replace my local file from C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets with the one from a different machine with a working build. Not quite sure why I had an older targets file. Possibly, at some point I installed an older version of Visual Studio and it updated the .targets file with the older version.

Categories: TFS Tags: Tags:

Hosting SignalR on GoDaddy in Full Trust

4 Comments

I had some free time recently and decided to learn a truly wonderful library SignalR. SignalR provides the “ability to have your server-side code push content to the connected clients as it happens, in real-time.” It eliminates the extra work of checking browser compatibility with whatever technology you decide to use for pushing the events to the client (WebSockets, EventSource, Long Polling, Forever Frame).

I implemented a simple Chat application using tutorial from Tim Teebken. It worked beautifully on local machine. However, when deployed to GoDaddy my application went down with System.Security.SecurityException. As it turns out, SignalR can run only in Full Trust mode. What I didn’t realize is that to enable full trust you have to explicitly specify Trust Level in Web.Config:

<configuration>
    <system.web>
        <trust level="Full" />
    </system.web>
</configuration>

Once this line was added to the configuration and deployed, my simple Chat client started working.

Categories: Web Tags: Tags: ,

Removing Duplicate Data from SQL Query Caused by New Line Character

No Comments

We had a query retrieving data from a linked Oracle server. We needed unique rows only. This is the original query:

SELECT Column
     FROM OPENQUERY( LinkedServer, 'SELECT DISTINCT Column from TABLE;' );

However, this still returned some duplicates despite using DISTINCT. As it turned out, some rows had a new line character in them. The solution:

SELECT distinct replace(replace(Column,CHAR(13),''),CHAR(10),'')
     FROM OPENQUERY( LinkedServer, 'SELECT DISTINCT Column from TABLE;' )
Categories: SQL Tags: Tags: