Thursday, December 30, 2010

Upgrade from Asp.Net MVC 1 to MVC 2 - how to and issues with JsonRequestBehavior

Goal

Upgrade your MVC 1 app to MVC 2

Issues

You may get errors about your Json data being returned via a GET request violating security principles - we also address this here. This post is not intended to delve into why the Json GET request is or may be an issue, just how to resolve it as part of upgrading from MVC1 to 2.

Solution

First remove all references from your projects to the MVC 1 dll and replace it with the MVC 2 dll. Now update your web.config file in your web app root folder by simply changing references to assembly="System.Web.Mvc, Version 1.0.0.0 to Version 2.0.0.0, there are a couple of references in your config file, here are probably most of them you may have:
        <compilation debug="true" defaultLanguage="c#">
           
        masterPageFile="~/Views/Masters/CRMTemplate.master" pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
            <controls>
                System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validateRequest="False">

Secondly, if you return Json objects from an ajax call via the GET method you ahve several options to fix this depending on your situation:
1. The simplest, as in my case I did this for an internal web app, you may simply do:
            return Json(myObject, JsonRequestBehavior.AllowGet);

2. In Mvc if you have a controller base you could wrap the Json method with:
        public new JsonResult Json(object data)
        {
            return Json(data, "application/json", JsonRequestBehavior.AllowGet);           
        }

3. The most work would be to decorate your Actions with:
        [AcceptVerbs(HttpVerbs.Get)]

4. Another tnat is also a lot of work that needs to be done to every ajax call returning Json is:
                            msg = $.ajax({ url: $('#ajaxGetSampleUrl').val(), dataType: 'json', type: 'POST', async: false, data: { name: theClass }, success: function(data, result) { if (!result) alert('Failure to retrieve the Sample Data.'); } }).responseText;

This should cover all the issues you may run into when upgrading. Let me kow if you run into any other ones.

jQuery 1.4.4 - issue with attr('selected', null)

Issue:
The code below worked before under version jQuery 1.4.2 but when I upgraded to version 1.4.4 it no longer worked as expected - it did not unselect the list box item, only setting "selectd" worked:
        _handleClick: function(elem) {
            var self = this; var initElem = this.element;
            var checked = $(elem).attr('checked');
            var myId = elem.attr('id').replace(initElem.attr('id') + '_chk_', '');
            initElem.children('option[value=' + myId + ']').attr('selected', function() {
                if (checked) {
                    return 'selected';
                } else { return null; }
            });

            if ($.isFunction(self.options.onItemSelected)) {
                try {
                    self.options.onItemSelected(elem, initElem.children('option').get());
                } catch (ex) {
                    if (self.options.allowDebug)
                        alert('select function failed: ' + ex.Description);
                }
            }
        },
Solution:
Under jQuery 1.4.4 you need to explicitly remove the attribute as in "removeAttr('selected'):
        _handleClick: function(elem) {
            var self = this; var initElem = this.element;
            var checked = $(elem).is(':checked');
            var myId = elem.attr('id').replace(initElem.attr('id') + '_chk_', '');
            if (checked) {
                initElem.children('option[value=' + myId + ']').attr('selected', 'selected');
            } else {
                initElem.children('option[value=' + myId + ']').removeAttr('selected');
            }
            if ($.isFunction(self.options.onItemSelected)) {
                try {
                    self.options.onItemSelected(elem, initElem.children('option').get());
                } catch (ex) {
                    if (self.options.allowDebug)
                        alert('select function failed: ' + ex.Description);
                }
            }
        },

Tuesday, December 14, 2010

After restoring a SQL Server database from another server - get login fails

Issue:

After you have restored a sql server database from another server, lets say from production to a Q/A environment, you get the "Login Fails" message for your service account.

Reason:

User logon information is stored in the syslogins table in the master database. By changing servers, or by altering this information by rebuilding or restoring an old version of the master database, the information may be different from when the user database dump was created. If logons do not exist for the users, they will receive an error indicating "Login failed" while attempting to log on to the server. If the user logons do exist, but the SUID values (for 6.x) or SID values (for 7.0) in master..syslogins and the sysusers table in the user database differ, the users may have different permissions than expected in the user database.

Solution:

Links a user entry in the sys.database_principals system catalog view in the current database to a SQL Server login of the same name. If a login with the same name does not exist, one will be created. Examine the result from the Auto_Fix statement to confirm that the correct link is in fact made. Avoid using Auto_Fix in security-sensitive situations.

When you use Auto_Fix, you must specify user and password if the login does not already exist, otherwise you must specify user but password will be ignored. login must be NULL. user must be a valid user in the current database. The login cannot have another user mapped to it.
execute the following stored procedure, in this example the login user name is "MyUser"
exec sp_change_users_login 'Auto_Fix', 'MyUser'

NOTE:
sp_change_users_login cannot be used with a SQL Server login created from a Windows principal or with a user created by using CREATE USER WITHOUT LOGIN.After restoring a SQL Server database from another server - get login fails

Thursday, December 2, 2010

Maximum request length exceeded.

Issue:
The file upload size on your machine or web app is too small. The default file upload size for IIS is 4096K. The file size the user is trying to add can be retrieved (using the ELMAH log here) by looking at the Content-Length header property:

HTTP_CONNECTION:keep-alive HTTP_KEEP_ALIVE:115 HTTP_CONTENT_LENGTH:6414851

In this example it is just over 6Mb

Solution:
You can add/update the HttpRuntime property in the machine or web config files, depending on at what level you want to set the size. For web-server level, impacting all web-apps running on that machine specify the following in the node of the machine.config file to allow less than 1Mb:

      <system.web>
<httpRuntime maxRequestLength="1000" />

If you want to set it, bigger, smaller or block at the web-app level you can specify it by adding the property above to the web.config file of that web app and it will only affect that web app.

For example I would like to maintain the default 4096K size limitation on my server except for the accounting web app and therefore set the accounting web-sites virtual directory web-config file to handle 8Mb file uploads:

      <system.web>
<httpRuntime maxRequestLength="8192" />

Resetting/Restoring the Windows PATH

Problem:

For some reason you lost your Windows PATH settings and want to restore the previous version:

Solution:

First of you may reset it to the original setting to:

Windows XP:     C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;{plus program paths}
Windows 7:     C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;{plus program paths}

Alternatively you could look for some previous version of the path in the registry. In Windows 7 you would look for "Path" name under Computer\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment. If you do not see the previous version of what you would expect, continue down the list "ControlSet002", "..03", etc. The current version will be under Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\....

Tuesday, November 30, 2010

Combine and compress javascript and css files in ASP.Net MVC

Goal:

When loading js or css files, combine all the js files into one and all css files into one file respectively when rendering to improve on performance. Also compress if need be on the fly.

In this example we use many css files and even more js files to organize the ASP.Net Mvc web app into manageable pieces. The reason for the separation is mainly because it gives the team the ability to work on different part of the web app by working on the affected css or js files. It also helps to decide at a very granular level which css or js files to load and cache in the browser and which ones are very unique and/or specific and/or large so as to load only when really needed. For example I have an extremely large contract page with about 4000 lines of jQuery to handle a spreadsheet like functionality. It is not used often and used only by certain sales reps. Do not want to load this file as part of the generic/global js file since it would be wasted space for most part. This file is loaded on the fly when needed. How that is done is another story :-) Since my app is a CRM app, it has many screens that have unique css styling requirements and so in some situations the css file should only be loaded when needed. The reasons are really not that important in the context of this blog, just want to show you how to do this in ASP.Net Mvc if and when the need arises.

System Requirements:

.Net 2+

ASP.Net Mvc v1+

Solution:


In your Master file head section


<link rel="stylesheet" type="text/css" href="<%=Url.RouteUrl(new {controller = "Scripts", Action = "GetAllCss"})%>" />

<script type="text/javascript" src="<%=Url.RouteUrl(new {controller = "Scripts", Action = "GetAllScripts"})%>"></script>

In the Mvc ScriptController controller:


public static IPathMapper ServerPathMapper { get; set; }


protected static bool Enable;

protected static bool EnableHtmlCompression;

protected static bool EnableHtmlMinification;

protected static bool EnableProfiler;

protected static bool EnableScriptCompression;

protected static bool EnableScriptMinification;

protected string Css = "css";

protected string Js = "js";


[OutputCacheAttribute(CacheProfile = "Scripts")]

public FileResult GetAllScripts()

{

StringBuilder sb = LoadjQueryScripts();

sb.Append(LoadCRMScripts());


return StreamText(sb.ToString(), Js);

}

[OutputCacheAttribute(CacheProfile = "CRMScripts")]

public static StringBuilder LoadjQueryScripts()

{

string min = "";



if (ScriptOptimizerConfig.EnableMinimizedFileLoad)

min = "Min/";



var sb = new StringBuilder(CombineLikeDirectoryFiles(String.Format("~/Scripts/jquery/Base/{0}", min), FileType.js));

//var sb = new StringBuilder(CombineLikeDirectoryFiles(String.Format("~/Scripts/jquery/Plugins/{0}", min), FileType.js));

sb.Append(CombineLikeDirectoryFiles(String.Format("~/Scripts/jquery/Plugins/{0}", min), FileType.js));

sb.Append(CombineLikeDirectoryFiles(String.Format("~/Scripts/jquery/Plugins/jquery.grid/{0}", min), FileType.js));

sb.Append(CombineLikeDirectoryFiles(String.Format("~/Scripts/jquery/Plugins/jquery.datepick/{0}", min), FileType.js));

sb.Append(CombineLikeDirectoryFiles(String.Format("~/Scripts/jquery/Plugins/jquery.flot/{0}", min), FileType.js));

return sb;

}



[OutputCacheAttribute(CacheProfile = "CRMScripts")]

public static StringBuilder LoadCRMScripts()

{

string pathForCRMScripts = GetPathForCRMScripts();



if (ScriptOptimizerConfig.EnableMinimizedFileLoad)

{

string newPathForCRM = pathForCRMScripts + "Min/";



if (Directory.Exists(ServerMapPath(newPathForCRM)))

pathForCRMScripts = newPathForCRM;

}



var sb = new StringBuilder(GetFile(pathForCRMScripts, "CRMScripting.js"));

sb.Append(GetFile(pathForCRMScripts, "CRMScriptingAccount.js"));

sb.Append(GetFile(pathForCRMScripts, "CRMScriptingContact.js"));

sb.Append(GetFile(pathForCRMScripts, "CRMScriptingCallSheet.js"));



return sb;

}


public FileStreamResult StreamText(string inputText, IEquatable<string> name)

{

if (name.Equals(Js) && ScriptOptimizerConfig.Enable && ScriptOptimizerConfig.EnableScriptMinification)

inputText = new JavaScriptCompressor(inputText, false).Compress();

if (name.Equals(Css) && ScriptOptimizerConfig.Enable && ScriptOptimizerConfig.EnableCssMinification)

inputText = CssCompressor.Compress(inputText, 0, CssCompressionType.MichaelAshRegexEnhancements);

var m = new MemoryStream(Encoding.Default.GetBytes(inputText));

return File(m, name.Equals(Css) ? "text/css" : "text/javascript");

}



public static string CombineLikeDirectoryFiles(string directory, FileType typeOfFile)

{

string combinedFiles = string.Empty;

string extension = null;



switch (typeOfFile)

{

case FileType.js:

extension = "js";

if (ScriptOptimizerConfig.EnableMinimizedFileLoad)

{

string newPath = string.Format("{0}{1}", directory, directory.EndsWith("/") ? "Min" : "/Min");



if (Directory.Exists(ServerMapPath(newPath)))

directory = newPath;

}

break;

case FileType.css:

extension = "css";

break;

}



if(extension == null)

return null;



if (GetFiles(directory, extension) != null)

{

foreach (FileInfo file in GetFiles(directory, extension))

{

using (var s = new StreamReader(file.FullName))

combinedFiles += s.ReadToEnd();

}



} return combinedFiles;

}





public static string GetFile(string pathForCRMScripts, string file)

{

if (ServerPathMapper != null)

{

string fullFilePath = ServerPathMapper.MapPath(pathForCRMScripts) + file;

if (!System.IO.File.Exists(fullFilePath))

return null;

using (var s = new StreamReader(fullFilePath))

return s.ReadToEnd();

}



return null;

}



public static IList<FileInfo> GetFiles(string serverPath, string extention)

{

string path = ServerMapPath(serverPath);



if (!Directory.Exists(path))

return null;



IList<FileInfo> files = new List<FileInfo>();



string[] fileNames = Directory.GetFiles(path, "*." + extention, SearchOption.TopDirectoryOnly);

foreach (string name in fileNames)

files.Add(new FileInfo(name));



return files;

}



public static string ServerMapPath(string serverPath)

{

if (!serverPath.StartsWith("~/"))

{

if (serverPath.StartsWith("/"))

serverPath = "~" + serverPath;

else

serverPath = "~/" + serverPath;

}

if (ServerPathMapper != null)

{

string path = ServerPathMapper.MapPath(serverPath);

if (!path.EndsWith("/"))

path = path + "/";

return path;

}



return null;

}


public static string GetPathForCRMScripts()

{

return "~/Scripts/CRM/";

}


public interface IPathMapper

{

string MapPath(string relativePath);

string MapPath();

}


The IPathMapper is injected via the ScriptController's constructor via IoC with Castle Windsor's windsor.boo config file:


Component "pathMapper", IPathMapper, Vert.CRM.UI.Mechanics.ServerPathMapper


public class ServerPathMapper : IPathMapper

{

private readonly string _relativePath;



public ServerPathMapper()

{

}



public ServerPathMapper(string relativePath)

{

_relativePath = relativePath;

}



#region Implementation of IPathMapper



public string MapPath(string relativePath)

{

return HttpContext.Current.Server.MapPath(relativePath);

}



public string MapPath()

{

if (_relativePath != null)

if (HttpContext.Current != null) return HttpContext.Current.Server.MapPath(_relativePath);



return null;

}



#endregion

}


The static properties to enable profiler, compression, minification is set by using the ScriptOptimizerSection class which inherits from ConfigurationSection:


public class ScriptOptimizerSection : ConfigurationSection {



[ConfigurationProperty("enable", IsRequired = true)]

public bool Enable {

get { return (bool)this["enable"]; }

set { this["enable"] = value; }

}

[ConfigurationProperty("enableProfiler", IsRequired = true)]

public bool EnableProfiler {

get { return (bool)this["enableProfiler"]; }

set { this["enableProfiler"] = value; }

}

[ConfigurationProperty("enableScriptCompression", IsRequired = true)]

public bool EnableScriptCompression {

get { return (bool)this["enableScriptCompression"]; }

set { this["enableScriptCompression"] = value; }

}

[ConfigurationProperty("enableHtmlCompression", IsRequired = true)]

public bool EnableHtmlCompression {

get { return (bool)this["enableHtmlCompression"]; }

set { this["enableHtmlCompression"] = value; }

}

[ConfigurationProperty("enableScriptMinification", IsRequired = true)]

public bool EnableScriptMinification {

get { return (bool)this["enableScriptMinification"]; }

set { this["enableScriptMinification"] = value; }

}

[ConfigurationProperty("enableHtmlMinification", IsRequired = true)]

public bool EnableHtmlMinification {

get { return (bool)this["enableHtmlMinification"]; }

set { this["enableHtmlMinification"] = value; }

}



[ConfigurationProperty("enableCssMinification", IsRequired = true)]

public bool EnableCssMinification {

get { return (bool)this["enableCssMinification"]; }

set { this["enableCssMinification"] = value; }

}



[ConfigurationProperty("enableMinimizedFileLoad", IsRequired = true)]

public bool EnableMinimizedFileLoad

{

get { return (bool)this["enableMinimizedFileLoad"]; }

set { this["enableMinimizedFileLoad"] = value; }

}

}



public class ScriptOptimizerConfig {



protected static bool enable;

protected static bool enableProfiler;

protected static bool enableScriptCompression;

protected static bool enableHtmlCompression;

protected static bool enableScriptMinification;

protected static bool enableHtmlMinification;

protected static bool enableCssMinification;

protected static bool enableMinimizedFileLoad;



/// <summary>

///

/// </summary>

static ScriptOptimizerConfig() {

ScriptOptimizerSection section;

section = (ScriptOptimizerSection)ConfigurationManager.GetSection("OptimizeClientSide");

if (section != null)

{

enable = section.Enable;

enableProfiler = section.EnableProfiler;

enableScriptCompression = section.EnableScriptCompression;

enableHtmlCompression = section.EnableHtmlCompression;

enableScriptMinification = section.EnableScriptMinification;

enableHtmlMinification = section.EnableHtmlMinification;

enableCssMinification = section.EnableCssMinification;

enableMinimizedFileLoad = section.EnableMinimizedFileLoad;

}

}



/// <summary>

///

/// </summary>

public static bool Enable {

get { return enable; }

}

/// <summary>

///

/// </summary>

public static bool EnableProfiler {

get { return enableProfiler; }

}

/// <summary>

///

/// </summary>

public static bool EnableScriptCompression {

get { return enableScriptCompression; }

}

/// <summary>

///

/// </summary>

public static bool EnableHtmlCompression {

get { return enableHtmlCompression; }

}

/// <summary>

///

/// </summary>

public static bool EnableScriptMinification {

get { return enableScriptMinification; }

}

/// <summary>

///

/// </summary>

public static bool EnableMinimizedFileLoad

{

get { return enableMinimizedFileLoad; }

}

/// <summary>

///

/// </summary>

public static bool EnableHtmlMinification {

get { return enableHtmlMinification; }

}



public static bool EnableCssMinification

{

get { return enableCssMinification; }

}

}


The web.config file settings for optimization settings:


<configuration>



<configSections>

<sectionGroup name="elmah">

<section name="errorLog" type="Elmah.ErrorLogSectionHandler,Elmah" />



</sectionGroup>

<section name="OptimizeClientSide" type="Vert.CRM.Core.Utility.ScriptOptimizerSection, Vert.CRM.Core" />

....


<OptimizeClientSide enable="false"

enableScriptCompression="false"

enableHtmlCompression="false"

enableScriptMinification="false"

enableMinimizedFileLoad="true"

enableHtmlMinification="false"

enableCssMinification="false"

enableProfiler="false">

</OptimizeClientSide>




Wednesday, November 24, 2010

Loading CSS stylesheet for ascx ASP.Net user control

Goal:

For performance reasons you want to load a piece of CSS only for the ascx file to which it applies. You do not want to embed the style as you cannot do this in ASP.Net ascx user controls. ASP.Net will render the style tag as HTML text.

Solution:

Some folks use the Page.Header.Controls.Add to add the stylesheet link in the ascx page or in the code behind. Not needed, you may specify a "link" tag in the ascx file, not need to specify "head" tag or anything else, just the link tag itself:




<link rel="Stylesheet" media="screen" type="text/css" href="<%=ResolveUrl("~/Content/StyleSheets/Screen/Global/CssCRMUITrafficLine.css") %>" />


The benefits are significant in that it is only loaded when needed. Personally I also prefix all my css selectors with the unique ID of the ascx container (i.e. I give the outer most div of my ascx page a unique name - usually that of the ascx file name) so that when I nest the ascx file into any other file the nested dynamically loaded CSS to not affect anything else outside of its scope. Also, since the stylesheet is linked it is cached on the user's browser once it has been loaded.


How to store arbitrary data in the DOM using jQuery

Goal:

Storing arbitrary data inside the DOM

Issue:

Storing data : $('selector').attr('alt', 'my data');

Retrieving data: $('selector').attr('alt');

The ALT attribute is designed to be an alternative text description. For images the ALT text displays before the image is loaded. ALT is a required element for images and can only be used for image tags because its specific purpose is to describe images.So therefore, "alt" is an HTML attribute meant to give the tag meaning and not to store data. Also if you want to store the same data for different DOM objects than the data is duplicated for every DOM property found in the selector

The solution:

Storing data   : $('selector').data('key', 'my data');                  $('selector').data('key', function() { do something } );
Retrieving data: $('selector').data('key');

The data is not stored in the DOM, it is stored jQuery's reference to that object, so for each target found by the selector only a reference is stored and the data is stored once and referenced as many times as needed.

Monday, November 22, 2010

Images do not appear on my SSR report

Problem:

You dynamically (or not) set the URL for the image you want to display in an SSRS report but it does not display the image (red x).

The reason:

SSRS access the images folder with anonymous access which is be default not allowed in IIS7 (not sure about IIS6 and prior versions).

The solution:

Make sure anonymous access is allowed to that images folder where the image resides that you are referencing via URL in SSRS Report. Also make sure that anonymous access is set to ENABLED in IIS for that same folder. If you set the security on the folder for anonymous to read only you will not have issues with someone deleting your images.

Wednesday, November 3, 2010

Setting select option index in jQuery

$('#myselect option:eq(1)').attr('selected', 'selected');

This will select the first option

Tuesday, October 12, 2010

jQuery - Get the text value of a single value selected from a drop down box

Goal:


Get the text value of a single option selected from a drop down box


Solution:


You have a drop down box called ALaCarteDiscount


$('#ALaCarteDiscount option:selected').text()


Tuesday, July 20, 2010

Large Cichlids

List of large Cichlids like Oscars, Jack Dempsey and the Electric Blue Jack Dempsey:


Large Cichlids

Monday, June 28, 2010

How to dynamically add Edit button to grid for editing row using the jqGrid formedit

Goal:

Dynamically add an Edit button to an empty column that will NOT trigger an inline edit but rather a jqGrid formedit for the selected row using the modal dialog option.

Problem:

All examples in the Demo version include editing inline and adding buttons to a column that only does an inline edit and the Demo version's getRowdata does not perform as expected. I tried it an could not get it working and the getRowData did not work as specified.

Solution:

gridComplete: function() {
var rows = $(item).jqGrid('getRowData');
for (var i = 0; i < rows[0].rows.length; i++) {
var row = rows[0].rows[i];
var idx = row.id;
if (!$(row).hasClass('jqgrow') && !$(row).hasClass('alt'))
continue;
var be = "";
$(item).setRowData(idx, { act: be });
$('#editAddress' + idx).click(function() {
$(item).editGridRow($(this).parent().parent('tr').attr('id'));
});
}
},


item = that is a variable that contains the id of my grid.

This is for editing an address so change the "editAddress" id prefix for your needs or create a generic function that will handle all of this:

gridComplete: function() {
SetupJqGridEditDeleteButtons(item);
},


function SetupJqGridEditDeleteButtons(item) {
var rows = $(item).jqGrid('getRowData');
for (var i = 0; i < rows[0].rows.length; i++) {
var row = rows[0].rows[i];
var idx = row.id;
if (!$(row).hasClass('jqgrow') && !$(row).hasClass('alt'))
continue;
var be = "";
$(item).setRowData(idx, { act: be });
$('#editItem' + idx).click(function() {
$(item).editGridRow($(this).parent().parent('tr').attr('id'));
});
}
}


Monday, June 14, 2010

TDD - Red-Light-Green_Light:: A critical view

Subject: The concept of red-light-green-light for TDD/BDD style testing has been around since the dawn of time (well almost). Having written thousands of tests using this approach I find myself questioning the validity of the principle

The issue:

False positive or a valid test strategy that can be trusted?

A critical view:

I agree that the red-green-light concept has some validity, but who has ever written 2000 tests for a system that goes through a ton of chnages due to the organic nature fo the application and does not have to change, delete or restructure their existing tests? If you asnwer to the latter question is" "Yes I had a situation(s) where I had to refactor my code and it caused me to have to rewrite/change/delete my existing tests", read on, else press CTRL+ALT+Del :-)

Once a test has been written, failed the test (red light), and then you comlpete your code and now get the green light for the last test, the test for that functionality is now in green light mode. It can never return to red light again as long as the test exists, even if the test itself is not changed, and only the code it tests is changed to fail the test. Why you ask? because the reason for the initial red-light when you created the test is not guaranteed to have triggered the initial red-light result for the same reasons it is now failing after a code change has been made.

Furthermore, when the same test is changed to compile correctly in case of a compile-breaking code change, the green-light once again has been invalidated. Why? Because there is no guarantee that the test code fix is in the same green-light state as it was when it first ran successfully.

To make matters worse, if you fix a compile-breaking test without going through the red-light-green-light test process, your test fix is essentially useless and very dangerous as it now provides you with a false-positive at best. Thinking your code has passed all tests and that it works correctly is far worse than not having any tests at all, well at least for that part of the system that the test-code represents.

What to do?

My recommendation is to delete the tests affected, and re-create them from scratch. I have to agree. Hard to do and justify if it has a significant impact on project deadlines.

What do you think?


Friday, April 30, 2010

jQuery - check/uncheck a checkbox

$('#PrimaryContacts').unbind().change(function() {
if ($('#PrimaryContacts option:selected').val() == 0) {
$('#filterPrimaryContact').removeAttr('checked').trigger('click');
}
else {
$('#filterPrimaryContact').trigger('click');
}

});


Also, in the example above, triggering the checkbox does not change the checkbox value. As depicted above, based on a dropdown box changing and no contact being selected from the drop down box, automatically uncheck the checkbox and trigger it in invoke any event handlers on the checkbox.

Monday, March 22, 2010

jscompress fails to compress my js file and errors out - why?

Issue:

You use the online compression utility jscompress.com to compress your js file but it fails with an error. Why this may be happening and how to fix it.

Possible causes:

Apparently not using open and closing curly brackets in an IF statement would cause this. Well turns out this is not the case. Look at the following example and see if you can figure out what the issue is :-)




function SetupDeliveredVPRecontactNotes($item, id) {
var theData;

$.ajax({
data: { deliveredVPId: id },
url: $('#ajaxGetDeliveredVPRecontactNotesUrl').val(),
type: "GET",
async: false,
dataType: "html",
success: function(data, result) {
$item.empty();

var input = '';
$item.append('input');
theData = data;
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
$item.empty();
alert("An error occurred: The operation to retrieve the DeliveredVP's Recontact Notes has failed");
}
}); //ajax

return theData;
}


Solution:

The issue is the closing textarea tab, concatenate it as

''
will fix the issue

Monday, March 15, 2010

How to check off a checkbox using jQuery

$('#someCheckbox').attr('checked','true')

Tuesday, February 9, 2010

How to find out if you are runnig on a 64-bit Processor

Goal:

Find out if you are runing on a 64-bit processor

Answer:

Go to the command prompt (type cmd int the Start -> Search box)

type the follownig command: set | find "PRECESSOR_ARCHITECTURE"

If you get ADM64 back (or something similar with 64 in it) you are running on a 64-bit processor, and would be able to install and run for example Windows 7's 64 bit OS. If you get something like x86 you are running on the older 32-bit architecture.