Wednesday, December 1, 2010

JQuery Validate dependency-expressions for custom rules

JQuery Validate has a nice feature that allows you to specify dependency-expression that must hold for rule to kick in. For example standard 'required' rule might accept expression like this:
$("#myForm").validate({
rules: {
myTextbox: {
required: "#myCheckbox:checked"
}
}
});
This tells 'required' rule that it should be used only when myCheckbox is checked. However'required' is the only rule that comes out of box with an option to specify a condition under which it works. What should you do in case you need to make your own rule use dependency-expression?

To enable depedency behavior for a custom rule use the following code:

jQuery.validator.addMethod("greaterThanZero", function(value, element, param) {
if ( !this.depend(param, element) )
return "dependency-mismatch";
return this.optional(element) || (parseFloat(value) > 0);
}, "* Amount must be greater than zero");
The if statement here does the trick. It checks if dependecy-expression is satisfied before proceeding to validation. Build in 'required' rule is actually using the same mechanism.

Friday, October 29, 2010

MVC 2 automatic deployment on IIS 5 (Windows Xp)

When you're deploying MVC application on IIS 5 you have to add wildcard '.*' mapping associated with isapi dll. IIS 6 and IIS 7 do that job for you for free.

Basically when you're doing it with your own hands you have to configure mappings in IIS manager. The scheme step by step is:
1. Open IIS manager.
2. Find your Website/Virtual Directory.
3. Open Properties window of that site/directory and find Configure button and add mapping for extension ".*" targeting aspnet_isapi.dll located in C:\Windows\Microsoft.NET\Framework\\

After that your extensionless URLs will be picked up by IIS and passed to MVC framework.

Now to the problem: what if I'm using WebDeploy to install my website on multiple machines that are all running IIS 5 (WinXp)? There must be some way to automate the process of adding of wildcard mapping to newly created website. And there is.

After doing some research I've bumped into the page on quite an old web site named IISFAQ.com. There they use VBScript to add any extension mapping scheme to existing website (http://www.iisfaq.com/Default.aspx?tabid=2792).

The script isnt very readable (its VBScript after all), so to narrow it down here is a simplified version that just adds wildcard mapping:
option Explicit

Dim ObjectPath,IISOBJ,NewScriptMaps
' Path to website/virtual directory, note that '1' before the root is the number of website used
ObjectPath = "IIS://localhost/W3SVC/1/ROOT/Test"

' Reading script maps that associate file extensions to applications
' and adding wildcard *. This wildcard should be processed by ASP.NET
' so we point at aspnet_isapi.dll. This way we can use ASP.NET MVC
' with extensionless URLs like http://localhost/home/index.
SET IISOBJ = getObject(ObjectPath)
NewScriptMaps = IISOBJ.ScriptMaps
Redim preserve NewScriptMaps(Ubound(NewScriptMaps)+1)

' 1 in the following line means that checkbox that says "Check that file exists"
' will be unchecked. That's a requirement, because ASP.NET MVC address points at
' the controller and method, not an actually existing file.
NewScriptMaps(ubound(NewScriptMaps)) = "*,C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll,1,GET,HEAD,POST,DEBUG"
IISOBJ.ScriptMaps = NewScriptMaps
IISOBJ.SetInfo

if (ERR <> 0) then
WScript.Echo "TERMINATING -- Error setting data - " & Err.Description & " (" & Err & ")"
WScript.Quit(1)
end if

This script will add wildcard mapping to virtual directory named "Test" of the first website on the local machine. All you have to do now is to integrate this .vbs into your deployment script, enjoy.

P.S. This script works with IIS 6 as well. Though if you're using .NET 4.0 there is no need to use wildcard mapping with IIS 6 unless you have dots in your URL scheme (like "http://localhost/Home/Index.Test"). IIS 5 requires wildcard mapping no matter what your addresses look like.

Thursday, October 29, 2009

Organizing mutiple Visual Studio solutions and multiple SVN repositories

Often when developing a project that has many components solution grows so big that it becomes quite messy, VS lags. When you check out Editor you'd like to work with you have to drag rest projects sitting there in repository. And so on.

The typical scheme will look like this:
What do we have here? We have project Core that holds domain objects and logic. Next in the same solution we have ReportsGenerator settled down. Also there some of your mates work on editor that also is using Core project indirectly.
Now say you want to develop/bugfix/just check what's going on in your ReportsGenerator. You have to checkout whole repository full of other logical parts like Editor and load big-ball-of-mud-solution with alot of files you dont care about at all.

However when working with VS solution you're able to reference project from another solution so it isnt nessesary to work with one big solution at all. You create your own solution ReportsGenerator, inside of it you create projects you would like to work with and then you reference to Core project of another solution. The developer working on Editors does pretty much the same thing. So now you both have references to the same Core project while working in 2 separate solutions.

Now lets think how does this work with SVN repository. One way is to keep everything in single repository. That way when you would like to checkout your ReportsGenerator solution you're in trouble: which referenced projects should be checked out as well? How will you know that ReportsGenerator is dependant on Core? Maybe it also has dependecies in Controllers project?

To solve this problem SVN repository externals property can be used. Whole picture is going to look like this:


Every solution now sits in its separate repository allowing easy check outs.

With externals tuned another developer checking out WPF_Editor code from its separate repository will also trigger check out for Controlers repository and Core repository. And he will work in his own separate solution for WPF_Editor. He has full access to Core solution, he can alter some classes and check them in, everyone else working on other dependant projects will notice that Core changed and can update it with SVN as usual.

Externals property can be used to reference a specific revision of folder in another repository so you wont get surprised when 3rd party library drastically changes.

Good guide into externals properties of SVN can be found here:

Thursday, August 13, 2009

Problems with conversion operator in abstract classes

Sad truth - no way to implement operator convertion in abstract class like this:
public abstract class DoubleValueBase
{
protected DoubleValueBase(double value)
{
AssertThatValueIsWithinRange(value);
this.Value = value;
}
public double Value { get; private set; }
public static implicit operator DoubleValueBase(double value)
{
return (DoubleValueBase)Activator.CreateInstance(??);
}
public static explicit operator double(DoubleValueBase value)
{
return value.Value;
}
protected abstract void AssertThatValueIsWithinRange(double value);
}
So it isn't possible to derive Power class from DoubleValueBase and write

Power power = 5.3;

unless you create implicit convertion operator in Power class. Now imagine, that you need to have 20 classes derived from DoubleValueBase.

P.S. If anybody have an idea if it is possible to do with languages like Boo or Nemerle give me a call please.

Tuesday, August 4, 2009

ValidateLambdaArgs and problems with casting linq Expression

Was stuck with a problem while implementing strogly typed mappings via linq expressions for a while. The problem was with passing Expression into method with reflection.

typeof(SomeClassRepository)
.GetMethod("LoadBy")
.Invoke(repository, new object[] { lambdaExpression, valueToMatch });
Actual signature of LoadBy looks like this:
public SomeClass LoadBy(Expression<Func<SomeClass, object>> expression, string value)
I want to build expression like x=>x.SomeProperty and pass it to LoadBy via reflection. The problem however arise its head when trying to pass value types when building expression:

var intPropertyName = "IntProperty";

var type = typeof(SomeClass);
var parameterExpression = Expression.Parameter(type, "x");
var memberExpression = Expression.Property(parameterExpression, intPropertyName);
var delegateType = typeof(Func<,>).MakeGenericType(new Type[] { type, typeof(object) });

var lambdaExpression = Expression.Lambda(delegateType,memberExpression, new[] { parameterExpression });

Here's definition of SomeClass:
public class SomeClass
{
public int IntProperty { get; set; }
}
Building such lambda expression raises System.ArgumentException in System.Linq.Expressions.Expression.ValidateLambdaArgs. Exception will say that you cannot use System.Int32 for return type System.Object.

To avoid this I found no way other than to use more reflection stuff and make a hack. Building lambda expression with following code instead of Expression.Lambda(...) fixed the problem:

var onlys = new ReadOnlyCollection<ParameterExpression>(new List<ParameterExpression> { parameterExpression });
var specificType = typeof(Expression<>).MakeGenericType(new System.Type[] { delegateType });
var lambdaExpression = Activator.CreateInstance(specificType,
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { memberExpression, onlys },
null);

Wednesday, July 22, 2009

How to get type masked by Castle Dynamic Proxy

Hello there, back from my vacation.

When writing "ORM" for Sharepoint lists I've encountered a problem with Castle Dynamic Proxy. I had to get the type which was wrapped with proxy and had no way to get that type in any other way besides getting it from the proxy itself.
Here's a little hack that does that through reflection:
var objProxy = obj as IProxyTargetAccessor;
if (objProxy != null)
{
var proxyTargetType= (Type)objProxy.GetType().GetField("typeTokenCache").GetValue(objProxy);
}
Note, however, that implementation of Dynamic Proxy might change and this hack will stop working then.

P.S. If anybody knows how to do it in a "right" way, post please.

Thursday, June 18, 2009

Just got myself NDepend license!

Got myself NDepend pro license from Patrick Smacchia (lead dev). Patrick, thanks alot! ;)

In short NDepend is code base analyzer which might reveal many weak links in your solution and discover many ways to improve overall structure.

I'm going to post my finding about its features while exploring this tool.

P.S. There are alot of learning demos and screenshots on official site you might want to check.