• Links in asp.net

    There are serveral helper class which help to generate links.

    //When you generate link with the same controller 
    Html.ActionLink();
    
    
  • ajax header

    Most of the javascript library add a header, when it use ajax to make a http quest.

    x-requested-with: XMLHttpRequest
    
  • Expression, Expression Tree, Lamda, Lamda expression, IQueryable

    Expression trees in .net 3.5 provide an abstract way of representing code as a tree of objects, these objects are expressions. As it said, Expression tree is a tree of expressions, and expression tree is also an expression, a composite of expressions. In .net there is no such type ExpressionTree, they are all Expressions.

    Expression firstArgExpression = Expression.Constant(2);
    Expression secondArgExpression = Expression.Constant(3);
    Expression addExpressionTree = Expression.Add(firstArgExpression, secondArgExpression);
    

    Expression, and expression tree is not much fun, until it can do something. So to do something, and we need to compile it into code, and execute the code. This a multiple steps process. First we need to convert the expression tree into a DelegateReadyExpression, then we compile DelegateReadyExpression into delegate instance, which is essentially a method, and finally we execute the method. In .net there is no such class DelegateReadyExpression, it is actually named LambdaExpression. LambdaExpression is an abstract sub-class of Exppression, it has a method "public Delegate Compile();". You may ask, why named LambdaExpression, why not DelegateReadyExpression, I will cover later in this post. The following code does these steps.

    LambdaExpression lamdaExpression = Expression.Lambda(addExpressionTree);
    Delegate unTypedDelegate = lamdaExpression.Compile();
    object untypedResult = unTypedDelegate.DynamicInvoke();
    Console.WriteLine(untypedResult);
    

    Seemingly, the above code is not good enough. As LambdaExpression is not strongly typed. We need to create a strongly type LamdaExpression, which is Expression<T>.


    Expression<Func<int>> stronglyTypedLamdaExpression = Expression.Lambda<Func<int>>(addExpressionTree);
    Func<int> stronglyTypedDelegate = stronglyTypedLamdaExpression.Compile();
    int result = stronglyTypedDelegate();
    Console.WriteLine(result);
    

    So the purpose of expression, and expression tree is light weight code generation. But it still too complicated to use. If we want to generate the following method,

    bool IsStartedWith(string x, string y)
    {
      return x.StartsWith(y);
    }
    

    We need programatically to do the following.

    MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    var target = Expression.Parameter(typeof(string), "x");
    var methodArg = Expression.Parameter(typeof(string), "y");
    Expression[] methodArgs = new[] { methodArg };
    Expression call = Expression.Call(target, method, methodArgs);
    var lambdaParameters = new[] { target, methodArg };
    var lambda = Expression.Lambda<Func<string, string, bool>>(call, lambdaParameters);
    var compiled = lambda.Compile();
    Console.WriteLine(compiled("First", "Second"));
    Console.WriteLine(compiled("First", "Fir"));
    

    Seemingly this is too tedious. It turns out Lamda Expression is very good to represent the an expression tree. Here we just use lamda to represent lamda expression. There are two forms of lambda expression (type Expression), statement lamda, expression lamda. The body of statement lambda expression can contains statements, and expression lambda expression can only contains expression only. We already know that we can use lambda expression represent a anonymous method, delegate, like the following. Both statement lamda and expression can do that.

    Func<string, string, bool> IsStartedWith = (x, y) =>
    {
        return x.StartsWith(y);
    };
    //or
    Func<string, string, bool> IsStartedWith = (x, y) => x.StartsWith(y);
    
    
  • Namespace and Controller in asp.net mvc

    In .net a type has a namespace, if two type names are the same, but they live in different namespace, this is not a problem. So when asp.net resolve the type with the controller name, DefaultController factory by default does not care namespace. So if there are two Controllers with the sname name in your reference dlls, then there will be an exception saying ambigous controllers found. But you can help the DefaultControllerFactory to resolve this conflict using the follow sample code.

    string[] routeContollerSearchHints_NameSpace = new string[] { "MvcAppTest.Controllers" };
    string routeName = "Default";
    string url = "{controller}/{action}/{id}";
    object defaults = new { controller = "Home", action = "Index", id = "" };
    object constrants = null;
    routes.MapRoute(routeName, url, defaults, constrants, routeContollerSearchHints_NameSpace);
    
    
  • Test Example in System.Web.Mvc

    Because the mvc project and test project are seperate, we need the test project to see the internal member in System.Web.Mvc project, so there is a attribute in the mvc project.

    [assembly: InternalsVisibleTo("System.Web.Mvc.Test")]