Friday, July 31, 2009

Jquery for Select All Checkbox

A very common interface is a list of items with a checkbox to select each and them you perform an action on those selected. Typically you have a checkbox at the top to toggle all of the list. This script will take care of everything for you. You can exclude elements by checking the ID or name properties.

$(document).ready(function() {
$("#selectAllCheckBox").click(function() {
var checked_status = this.checked;
$("input[type=CheckBox]").each(function() {
if (this.id != "pleaseSkipMe") {
this.checked = checked_status;
}
});
});
});

Friday, July 24, 2009

Ajax Call Issue

When making an Ajax call, remember to make sure that your target element can accept the result of your call. For example, if I return a string from my call to a target element of <p>, everything is fine. Replace that with a table and you’ll get the lovely message “htmlfile: Unknown runtime error”. Change to a <div> and everything is fine.

Thursday, July 23, 2009

Asp.Net MVC Unit Testing Authorization

Asp.Net provides the Authorize attribute for checking to make sure you have an authenticated user and that they are in the correct role(s). Since this is part of the framework, I don’t need to test the attribute (that’s Microsoft’s job). I do want to test that I have applied the attribute with the correct properties.

Here’s my unit test code for checking that the attribute has been applied.

[TestMethod()]
public void Autorization_Attributes_Have_Been_Applied()
{

MethodInfo[] methodInfos = typeof(CustomersController).GetMethods(BindingFlags.Public |
BindingFlags.Static);

foreach (MethodInfo methodInfo in methodInfos)
{
ParameterInfo[] parmInfo = methodInfo.GetParameters();
if (methodInfo.Name == "Create" | methodInfo.Name == "Edit")
{
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsNotNull(attributes);
Assert.AreEqual(1, attributes.Length);
var authorizeAttribute = (AuthorizeAttribute)attributes[0];
Assert.IsTrue(authorizeAttribute.Roles.Contains(ApplicationRoles.ChangeCustomersGroup));
}

if (methodInfo.Name == "Index")
{
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsNotNull(attributes);
Assert.AreEqual(1, attributes.Length);
var authorizeAttribute = (AuthorizeAttribute)attributes[0];
Assert.IsTrue(authorizeAttribute.Roles.Contains(ApplicationRoles.ViewCustomersGroup));
}
}
}
Depending on how much you need to test, you can make sure that only specific roles are applied, etc. My sample above only checks for the Index, Create and Edit methods and allows all others to fall through. You could make it fail so that any public method that wasn’t checked failed the test. Remember, if it’s public on your controller it can be called.



Update: April 1, 2010 -- Josh has taken this to the next step. Check it out here.

UpdateModel Unit Testing Gotcha!

If you’re unit testing and make a call to UpdateModel, you get the case where your object doesn’t get updated.

Say your controller has an Edit Post action similar to:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Customer customer)
{
Customer _customer = repository.GetByKey(customer.CustomerKey);
UpdateModel(_customer);
repository.Save();
return RedirectToAction("Index");
}
Now you might think that the call to UpdateModel will use your the object you passed in. Wrong! It wants the form values that get passed as part of the post request. So if you’re unit testing and using MVC fakes, you need to pass in some form values.
Customer customer = new Customer()
{
CustomerKey = 1234,
CustomerName = "ABC Siding",
Address = "1 Main",
City = "Springfield",
State = "IL",
ZipCode = "62701",
FirstName = "Fred",
LastName = "Jones",
Phone = "2175551212",
Fax = "2175551213",
IsActive = true
};

NameValueCollection formParams = new NameValueCollection {
{ "CustomerName", customer.CustomerName },
{ "Address", customer.Address },
{ "City", customer.City },
{ "State", customer.State },
{ "ZipCode", customer.ZipCode },
{ "FirstName", customer.FirstName },
{ "LastName", customer.LastName },
{ "Phone", customer.Phone },
{ "Fax", customer.Fax },
{ "IsActive", customer.IsActive.ToString() }
};

target.ControllerContext = new FakeControllerContext(
target, "PaulBrown", new string[] { ApplicationRoles.ViewCustomersGroup },
null, formParams, null, null, null);
Once you pass in the form vars, everything works fine. Now the question I’m asking myself is why I’ve got an argument in the method signature at all. The answer is because that was how Scott Gu did it in NerdDinner. Gonna have to look at that!

Wednesday, July 22, 2009

Fake HttpResponse for Asp.Net MVC

Here’s an HttpResponse fake to go with Stephen Walther’s MVC Fakes. It’s based on his HttpRequest. If you need something for testing the cache, look here.

public class FakeHttpResponse
: HttpResponseBase
{
private HttpCookieCollection _cookies;
private NameValueCollection _headers;
private bool isClientConnected;
private bool isRequestBeingRedirected;
private TextWriter output;
private Stream outputStream;

public FakeHttpResponse(
NameValueCollection headers,
HttpCookieCollection cookies
)
{
this._headers = headers;
this._cookies = cookies;
}

public FakeHttpResponse(
NameValueCollection headers,
HttpCookieCollection cookies,
bool isClientConnected,
bool isRequestBeingRedirected,
TextWriter output,
Stream outputStream
)
{
this._headers = headers;
this._cookies = cookies;
this.isClientConnected = isClientConnected;
this.isRequestBeingRedirected = isRequestBeingRedirected;
this.output = output;
this.outputStream = outputStream;
}

public override HttpCookieCollection Cookies
{
get
{
if (this._cookies == null) { this._cookies = new HttpCookieCollection(); }
return this._cookies;
}
}

public override NameValueCollection Headers
{
get
{
if (this._headers == null) { this._headers = new NameValueCollection(); }
return this._headers;
}
}

public override bool Buffer { get; set; }

public override bool BufferOutput { get; set; }

public override string Charset { get; set; }
public override Encoding ContentEncoding { get; set; }
public override string ContentType { get; set; }
public override int Expires { get; set; }
public override DateTime ExpiresAbsolute { get; set; }
public override Stream Filter { get; set; }
public override Encoding HeaderEncoding { get; set; }
public override bool IsClientConnected { get {return isClientConnected;} }
public override bool IsRequestBeingRedirected { get {return isRequestBeingRedirected;} }
public override TextWriter Output { get {return output;} }
public override Stream OutputStream { get {return outputStream;} }
public override string RedirectLocation { get; set; }
public override string Status { get; set; }
public override int StatusCode { get; set; }
public override string StatusDescription { get; set; }
public override int SubStatusCode { get; set; }
public override bool SuppressContent { get; set; }
public override bool TrySkipIisCustomErrors { get; set; }
}

Tuesday, July 21, 2009

Unit Testing Asp.net MVC and the Cache

If you haven’t worked with Stephen Walthers MVC Tip #12, you’re missing out on a great way to test your MVC controllers. He provides fakes for the ControllerContext, HttpContext, HttpRequest, SessionState and also mechanisms for testing authorization. You can download his code at the end of the post.

I created a new project called MvcFakesForTesting and copied all of the classes. I did this so I can extend and grow the project. Stephen wrote his library with pre-release code, so I needed to change a couple of IController references to ControllerBase. I also created added Headers so that I can fake the request headers. Just implement this the same as QueryString and FormParams. Now I have the DLL that I will use on all of our projects for testing. I made sure to include a reference to Stephen so that credit is given where credit is due.

One thing that is not included is a fake for the Cache. Of course, I ran into this on my first test! First of all, the Cache object is sealed / notinheritable and doesn’t have an interface so mocking or faking it is not going to work. We’re going to need a wrapper.

Step one is to create an interface so I can create use dependency injection for testing. ICacheWrapper is simply all of the public methods from Cache.

public interface ICacheWrapper
{
int Count { get; }

object this[string key] { get; set; }

object Add(string key,
object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback);

object Get(string key);

void Insert(string key, object value);

void Insert(string key, object value, CacheDependency dependencies);

void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration);

void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);

void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);

object Remove(string key);
}

Now I can create  CacheWrapper that implements ICacheWrapper and defers the call to the actual cache.

public class CacheWrapper : ICacheWrapper
{
private Cache cache;

public CacheWrapper()
{
this.cache = HttpContext.Current.Cache;
}

public CacheWrapper(Cache cache)
{
this.cache = cache;
}

#region ICacheWrapper Members

public int Count
{
get { return this.cache.Count; }
}

public object this[string key]
{
get
{
return this.cache[key];
}
set
{
this.cache.Insert(key, value);
}
}

public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
return this.cache.Add(key, value, dependencies, absoluteExpiration, slidingExpiration, priority, onRemoveCallback);
}

public object Get(string key)
{
return this.cache[key];
}

public void Insert(string key, object value)
{
this.cache.Insert(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies)
{
this.cache.Insert(key, value, dependencies);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
this.cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback)
{
this.cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration, onUpdateCallback);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
this.cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration, priority, onRemoveCallback);
}

public object Remove(string key)
{
return this.cache.Remove(key);
}

#endregion
}

Now, anywhere I want to access the cache, I create a link to ICacheWrapper and provide a mechanism for injecting the wrapper. This makes the code the same whether I’m testing for production.

public class CustomersProxy
{
private ICacheWrapper cache;
private ICustomersRepository repository;

public CustomersProxy(ICustomersRepository repository, ICacheWrapper cache)
{
this.repository = repository;
this.cache = cache;
}

public List<Customer> ListCustomers()
{
List<Customer> customers = (List<Customer>)this.cache[CustomersCacheKey];
if (customers == null)
{
customers = repository.FindAll();
this.cache.Add(
CustomersCacheKey,
customers ,
null,
Cache.NoAbsoluteExpiration,
new TimeSpan(1, 0, 0),
CacheItemPriority.AboveNormal,
null);
}
return customers;
}
}

FakeCacheWrapper uses a Dictionary to act as the cache. It implements ICacheWrapper so we can inject it for testing anywhere we need to call the cache.

public class FakeCacheWrapper : ICacheWrapper
{
private readonly Dictionary<string, object> cacheItems;

public static readonly DateTime NoAbsoluteExpiration;

public static readonly TimeSpan NoSlidingExpiration;

public FakeCacheWrapper()
{
this.cacheItems = new Dictionary<string, object>();
}

public int Count { get { return this.cacheItems.Count; } }

public object this[string key]
{
get
{
return Get(key);
}
set
{
cacheItems.Add(key, value);
}
}

public object Add(string key,
object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback)
{
this.cacheItems.Add(key, value);
return value;
}

public object Get(string key)
{
if (this.cacheItems.ContainsKey(key))
{ return this.cacheItems[key]; }
return null;
}

public IDictionaryEnumerator GetEnumerator()
{ return this.cacheItems.GetEnumerator(); }

public void Insert(string key, object value)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
this.cacheItems.Add(key, value);
}

public object Remove(string key)
{
object obj = null;
if (this.cacheItems.ContainsKey(key))
{
obj = this.cacheItems[key];
}
this.cacheItems.Remove(key);
return obj;
}
}
Now my controller has an two constructors, one for production and one for testing.
public class CustomersController : Controller
{
private CustomersProxy proxy;

public CustomersController()
{
CacheWrapper wrapper = new CacheWrapper(HttpContext.Current.Cache);
CustomersRepository repository = new CustomersRepository();
this.proxy = new CustomersProxy(repository, wrapper);
}

public CustomersController(CustomersProxy proxy)
{
this.proxy = proxy;
}

.....
}

With Stephen’s fakes and ICacheWrapper/FakeCacheWrapper, I can now test just about everything I need to.

Friday, July 17, 2009

KVM Switch gives USB not recognized

My TrendNet TK409K KVM popped up with a “USB not recognized or malfunctioned” today. The solution I found was to unplug all of the USB connections for a minute. This apparently “resets” the box. Plug everything back in and away you go.

Wednesday, July 15, 2009

Make Internal Methods Visible for Unit Testing

Need to make your internal classes and methods visible to unit testing? Try the post. Works like a champ!

Tuesday, July 14, 2009

T-SQL to create an instance of an object with the properties set

Here’s some T-SQL to create a SELECT statement that will create the properties with values. I use this for generating test data from existing DB’s. Right now I’ve got it setup to handle int, char, varchar, smalldatetime, datetime and bit. I’ll add others as needed.

@TableName is the name of the table where the data is stored. Simply set the table name hit F5 then cut and paste the generated script into the T-SQL that gets the data your looking for. This can be all rows in the table or a single row.

The code:

declare @TableName varchar(100)
declare @ColumnName varchar(100)
declare @DataType varchar(100)
declare @Sql varchar(max)

declare @Crlf char(2)

set @TableName = 'Clients'
set @Sql = CHAR(39)

declare cols_temp cursor for
SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE Table_Name = @TableName
and data_type in ('int', 'char', 'varchar', 'smalldatetime', 'datetime', 'bit')

open cols_temp

FETCH NEXT FROM cols_temp INTO @ColumnName,@DataType

WHILE @@FETCH_STATUS = 0
BEGIN
IF LEN(@Sql) > 1
SET @Sql = @Sql + ' + ' + CHAR(39) + ', '

IF @DataType = 'int'
SET @Sql = @Sql + @ColumnName + ' = ' + CHAR(39) + ' + CAST(' + @ColumnName + ' As varchar)'

IF @DataType in ('char', 'varchar')
SET @Sql = @Sql + @ColumnName + ' = "' + CHAR(39) + ' + COALESCE(' + @ColumnName + ', '''') + ' + CHAR(39) + '"' + CHAR(39)

IF @DataType = 'bit'
SET @Sql = @Sql + @ColumnName + ' = '' + CASE WHEN ' + @ColumnName + '=1 THEN ''true'' ELSE ''false'' END'

IF @DataType = 'smalldatetime'
SET @Sql = @Sql + @ColumnName + ' = new DateTime('' + CAST(YEAR(' + @ColumnName + ') As varchar) + '', '' + CAST(MONTH(' + @ColumnName + ') As varchar) + '', '' + CAST(DAY(' + @ColumnName + ') As varchar) + '', 0, 0, 0)'''

IF @DataType = 'datetime'
SET @Sql = @Sql + @ColumnName + ' = new DateTime('' + CAST(YEAR(' + @ColumnName + ') As varchar) + '', '' + CAST(MONTH(' + @ColumnName + ') As varchar) + '', '' + CAST(DAY(' + @ColumnName + ') As varchar) + '', '' + CAST(DATEPART(HH,' + @ColumnName + ') As varchar) + '', '' + CAST(DATEPART(N,' + @ColumnName + ') As varchar) + '', '' + CAST(DATEPART(S,' + @ColumnName + ') As varchar) + '')'''

FETCH NEXT FROM cols_temp INTO @ColumnName,@DataType
END

SELECT @Sql

close cols_temp

deallocate cols_temp

Sample uses to add to rows to a collection:

SELECT 
'clientsCollection.Add(new Client() {ClientKey = ' + CAST(ClientKey As varchar)
+ ', FirstName = "' + COALESCE(FirstName, '') + '"'
+ ', LastName = "' + COALESCE(LastName, '') + '"'
+ ', MiddleInitial = "' + COALESCE(MiddleInitial, '') + '"'
+ ', Birth = new DateTime(' + CAST(YEAR(Birth) As varchar)
+ ', ' + CAST(MONTH(Birth) As varchar)
+ ', ' + CAST(DAY(Birth) As varchar) + ', 0, 0, 0) });'
FROM Clients
This generates the following:
clientsCollection.Add(new Client() { ClientKey = 52, FirstName = "Paul", LastName = "McCartney", MiddleInitial = "", Birth = new DateTime(1945, 10, 15, 0, 0, 0) });
clientsCollection.Add(new Client() { ClientKey = 43, FirstName = "George", LastName = "Harrison", MiddleInitial = "D", Birth = new DateTime(1943, 12, 17, 0, 0, 0) });
clientsCollection.Add(new Client() { ClientKey = 84, FirstName = "Ringo", LastName = "Starr", MiddleInitial = "A", Birth = new DateTime(1949, 12, 5, 0, 0, 0) });
Sample to create a specific instance:
SELECT 
'Client testClient = new Client() {ClientKey = ' + CAST(ClientKey As varchar) + ', FirstName = "' + COALESCE(FirstName, '') + '"' + ', LastName = "' + COALESCE(LastName, '') + '"' + ', MiddleInitial = "' + COALESCE(MiddleInitial, '') + '"' + ', Birth = new DateTime(' + CAST(YEAR(Birth) As varchar) + ', ' + CAST(MONTH(Birth) As varchar) + ', ' + CAST(DAY(Birth) As varchar) + ', 0, 0, 0) });'
FROM Clients
WHERE ClientKey = 52
This generates the following (I formatted the code):
Client testClient = new Client() {
ClientKey = 52,
FirstName = "Paul",
LastName = "McCartney",
MiddleInitial = "",
Birth = new DateTime(1945, 10, 15, 0, 0, 0)
};
Have fun!!!

Thursday, July 2, 2009

What’s in a name?

I’ve worked on database projects for over 20 years. I go back to FoxBASE and dBase. I’ve also been through a number of naming conventions in that time. I’ve developed a personal preference but can work with other preferences because I can usually figure them out fairly quickly.

Here’s two rules I use as part of my database designs:

  1. Use a surrogate or artificial key as the primary key to avoid the need for cascading deletes or updates.
  2. Use the natural name for each element so that elements are easily identifiable when in discussions with the user.

I can’t tell you how much time I have saved over the years with rule 2. Users have no idea of your database design (and they shouldn’t!) but they know exactly which piece of information they want. It’s a whole lot easier if they can write “client’s birth date” in a report request and in the Clients table there is a field called BirthDate.

My problem is lately, I’ve noticed that a lot of people seem to be using a convention that drives me nuts - the use of ElementNameID as the primary key. This is the standard in a lot of the Microsoft examples.

What's the big deal? In one of our systems we have a table named Clients that holds…wait for it..a client. That client has an ID that is assigned from a legacy mainframe system and of course it’s called ClientID. This element has become a part of the users culture and is used to identify clients and it’s natural name is Client ID in user discussions.

“So just make it your primary key and you’re fine.” Not so fast. Remember, this is coming from a legacy system, in this case a 25 year old system. In those days disk space was expensive and you squeezed everything you could into a field. Specifically, the first 6 positions are the family group and the last two differentiate between individuals.

My problem here is that since the value has internal meaning, someone, somewhere will want to change this value. For this reason, I always use artificial or surrogate keys (see rule 1). No worries about cascading updates or orphaned rows.

Ok, so now my clients will have two values named ClientID. One the actual key and the other a legacy key. I could use an underscore for one, i.e. Client_ID. I could simply rename the legacy value ClientIDLegacy. Either one means that everyone who looks at my data will have to figure out what I did.

Worse, the natural name and the database name are different, violating rule 2. I could use Client_ID for the key instead but that means I need to change all of my other tables to match or live with the inconsistency (meaning remember to use the underscore on this one table).

My solution? It’s very simple, ClientKey. The element we are describing is a key and not an ID. To me, ID (or identifier) is something to be consumed by humans. Keys are for systems. I really can’t remember something being called “key” in a non-IT environment.

It may seem trivial, but I can think of half a dozen cases of the top of my head where you’ll run into this. It may not get you on this system but how about the next one? Now you have two systems with two different conventions. Now you need to remember what you did in one and not in the other. After 20 years, I’m limiting what I need to remember only to those things I can’t control <g>!