Dec 17, 2009

A dummy example of html helper

public static class HtmlHelperExt
{
    public static string GetDebugInfo(this HtmlHelper html)
    {
        return "Hello";
    }

    public static void Debug(this HtmlHelper html)
    {
        var writer = html.ViewContext.HttpContext.Response.Output;
        writer.Write("

hello

"); } }

Dec 9, 2009

definition of two kinds of test

State-based testing (also called state verification)
determines whether the exercised method worked correctly by examining the state of the system under test and its collaborators (dependencies) after the method is exercised.
Interaction testing
is testing how an object sends input to or receives input from other objects—how that object interacts with other objects.

Nov 12, 2009

ResourceManager notes

The benefit to ResourceManager is that it can smartly load differently resource based on the current UI culture. ResourceManager basically it is used to read embedded resource or file based resource. But it is extensible. It has three constructor, and one static factory method

public ResourceManager(String baseName, Assembly assembly) 
public ResourceManager(Type resourceSource);


public ResourceManager(String baseName, Assembly assembly, Type usingResourceSet);
public static ResourceManager CreateFileBasedResourceManager(String baseName, String resourceDir, Type usingResourceSet) 

The most commonly used constructor is the first one. It try to read the embedded resource in the assembly, and the baseName is used to search inside of assembly. The second constructor basically does the same thing of first one. The type of resourceSource is the strongly type resource that is automatically generated by tool. This type has some static method to wrap the resource. Here is used to calcuated the base name, and assembly. Both of these two method use default RuntimeResourceSet to cache the resource. The third one allowed you specify the type of ResourceSet to cached the resource. This is useful if you have resource in different format. For example, if you baseName is "base", and dll name is "asm", the Resource manager will search in that dll for a resource named "asm.base.resources". By default it will use RuntimeResourceSet to cache the resource. But RuntimeResourceSet is internal, so that you can not use that. Following is clone of RuntimeResourceSet.

public RuntimeResourceSetClone(IResourceReader reader) : base(reader) { }

public RuntimeResourceSetClone(string fileName)
{
    ResourceReader reader = new ResourceReader(fileName);
    this.Reader = reader;
}

public RuntimeResourceSetClone(Stream stream)
{
    ResourceReader reader = new ResourceReader(stream);
    this.Reader = reader;
}

//we can use this ResourceSet to cache the default resource format
ResourceManager manager = new ResourceManager("UI", Assembly.GetExecutingAssembly(), typeof(RuntimeResourceSetClone));
Console.WriteLine(manager.GetString("Name"));

When you use resx file to manage resources, the compiler does not actually create resx format resource , and embed it in the assembly. What it does is to generate resource in defautlt resource format. Say you have UI.resx file, and the embedded resource name will be assemblyName.ui.resources. In case, you really want to use it in resources, you have to rename the extension to resources. The following shows how to read that. Please note the you need put the dll name with file name together.

//the loose file name is filename.resources
//the dll name is dllname
ResourceManager manager = new ResourceManager("dllname.filename", Assembly.GetExecutingAssembly(), typeof(ResXResourceSet));
Console.WriteLine(manager.GetString("Type"));

For embedded file resource, the neutral resource will be embedded in the main dll, for other resource, an assembly will be put in sub folder in the name of the culture (eg. zh-CN), the name of assembly is like mainAssemblyName.resources.dll.

The static factory method is used to read loose file in file system. One of the benefit using loose file is that saving memory, because resource is not loaded in the memory. All your resources file need to follow format, baseName.cultureName.resources . Yes, the extension has to be resources, even thought the content is not in resx format. Below is some example.

//if the resource format is default resource format, set usingResourceSet type to null,
var man = ResourceManager.CreateFileBasedResourceManager("baseName", "folderName", null);
Console.WriteLine(man.GetString("Name"));

//if resource file is in resx format, (the extension need to be ressources)
var man = ResourceManager.CreateFileBasedResourceManager("baseName", "folderName", typeof(ResXResourceSet));

The algorithm of ResourceManager depends on the UICulture heavily. First it locate the resource for current culture, if found return the value, if not fall back, to neutral culture, then invariant culture. For example, if current culture is zh-CN, it will try in the path of zh-CN, zh-CHS, Invariant. So to implement that, resource manager holds a ResourceSet for each availabe culture, depending how much culture the resources support. For each ResourceSet, it holds a Dictionary object to cache to resource. The dictionary is filled by IResourceReader in the consturctor of ResourceSet. After that resource will be disconnected because all resource is cached. The default RuntimeResourceSet is optimized, so it does not use the dictionary.

To extend ResourceManager, we just need implement how the ResourceSet is created, and how the resource is read by IResourceReader. The default ResourceSet interface is designed for file based resource.

public ResourceSet(Stream stream) 
public ResourceSet(IResourceReader reader) 
public ResourceSet(String fileName)

Because of ResourceManager will use the same interface to create ResourceSet, if your solution is also file based, you just need a ResoursSet follow this constructor pattern. And you don't need to create a new ResourceManager, that is how Resx file is implemented. But if your solution is not file based, you need to SubClass your ResourceManager as well. ResourceSet will use IResourceReader to build its dictionary. IResourceReader is actually very simple Another drawback of ResourceManager is lack of creating or updating resource.

public interface IResourceReader : IEnumerable, IDisposable
{
        void Close();
        IDictionaryEnumerator GetEnumerator();
}

CurrentCulture can not be set to Neutural Culture

var c = CultureInfo.GetCultureInfo("en");
Console.WriteLine(c.Name); //en
var c2 = CultureInfo.CreateSpecificCulture("en");
Console.WriteLine(c2); //en-US
Thread.CurrentThread.CurrentCulture = c2; //ok
//following with throw
//System.NotSupportedException: Culture 'en' is a neutral culture.
Thread.CurrentThread.CurrentCulture = c; 

Because of this, the following code is necessary

 if (Request.UserLanguages != null &&
        Request.UserLanguages.GetLength(0) > 0)
    {
        CultureInfo cultureInfo =
            new CultureInfo(Request.UserLanguages[0]);
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
        Thread.CurrentThread.CurrentCulture =
            CultureInfo.CreateSpecificCulture(cultureInfo.Name);
    }

This code gets the user's language preference from the first element of the Request.UserLanguages array. If the user's settings are such that, Request.UserLanguages[0] will be "en-US". We create a new CultureInfo object and assign it to CurrentUICulture. The next line uses CultureInfo.CreateSpecificCulture to create a specific culture from a potentially neutral culture. In this example the culture will be no different (i.e., it will be "en-US"), but if the original language preference was "en", the specific culture would be "en-US". Recall that this step is necessary because CurrentCulture must be culture-specific. Later in this chapter, we implement a more sophisticated version of this first attempt that iterates through each of the language preferences looking for a language that matches the application's supported languages.

Nov 11, 2009

How Routing Works in asp.net mvc

The mvc stack start with the UrlRoutingModule. The module handle two HttpApplication event.

/* the order of application event is:
OnBeginRequest
OnAuthenticateRequest
OnPostAuthenticateRequest
OnAuthorizeRequest
OnPostAuthorizeRequest
OnResolveRequestCache
OnPostResolveRequestCache --> handled by  PostResolveRequestCache
OnPostMapRequestHandler --> handled by PostMapRequestHandler
OnAcquireRequestState
OnPostAcquireRequestState
OnPreRequestHandlerExecute
Page_Load Event of the Page
OnPostRequestHandlerExecute
OnReleaseRequestState
OnPostReleaseRequestState
OnUpdateRequestCache
OnPostUpdateRequestCache
OnEndRequest
OnPreSendRequestHeaders */
public virtual void PostResolveRequestCache(HttpContextBase context) { 
    // Match the incoming URL against the route table
    RouteData routeData = RouteCollection.GetRouteData(context); 

    // Do nothing if no route found
    if (routeData == null) { 
        return;
    }

    // If a route was found, get an IHttpHandler from the route's RouteHandler 
    IRouteHandler routeHandler = routeData.RouteHandler;
    if (routeHandler == null) { 
        throw new InvalidOperationException( 
            String.Format(
                CultureInfo.CurrentUICulture, 
                RoutingResources.UrlRoutingModule_NoRouteHandler));
    }

    // This is a special IRouteHandler that tells the routing module to stop processing 
    // routes and to let the fallback handler handle the request.
    if (routeHandler is StopRoutingHandler) { 
        return; 
    }

    RequestContext requestContext = new RequestContext(context, routeData);

    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
    if (httpHandler == null) { 
        throw new InvalidOperationException(
            String.Format( 
                CultureInfo.CurrentUICulture, 
                RoutingResources.UrlRoutingModule_NoHttpHandler,
                routeHandler.GetType())); 
    }

    // Save data to be used later in pipeline
    context.Items[_requestDataKey] = new RequestData() { 
        OriginalPath = context.Request.Path,
        HttpHandler = httpHandler 
    }; 

    // Rewrite path to something registered as a managed handler in IIS.  This is necessary so IIS7 will 
    // execute our managed handler (instead of say the static file handler).
    context.RewritePath("~/UrlRouting.axd");
}

public virtual void PostMapRequestHandler(HttpContextBase context)
{
    RequestData requestData = (RequestData)context.Items[_requestDataKey];
    if (requestData != null)
    {
        // Rewrite the path back to its original value, so the request handler only sees the original path.
        context.RewritePath(requestData.OriginalPath);

        // Set Context.Handler to the IHttpHandler determined earlier in the pipeline.
        context.Handler = requestData.HttpHandler;
    }
}

The route matching is handled by "RouteData routeData = RouteCollection.GetRouteData(context);". It search the Routes defined in start up event. If RouteData is not found, the handling will be passed back. Below is the code how RouteCollection handle the matching.

//RouteCollection member
public RouteData GetRouteData(HttpContextBase httpContext) { 
//... code skip ...
    // Go through all the configured routes and find the first one that returns a match
    using (GetReadLock()) { 
        foreach (RouteBase route in this) {
            RouteData routeData = route.GetRouteData(httpContext);
            if (routeData != null) {
                //the first matching wins
                return routeData; 
            }
        } 
    } 
    return null; 
}

//Route member
public override RouteData GetRouteData(HttpContextBase httpContext) {
    // Parse incoming URL (we trim off the first two chars since they're always "~/")
    string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

    RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults); 

    if (values == null) {
        // If we got back a null value set, that means the URL did not match 
        return null;
    }

    RouteData routeData = new RouteData(this, RouteHandler); 

    // Validate the values 
    if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) { 
        return null;
    } 

    // Copy the matched values
    foreach (var value in values) {
        routeData.Values.Add(value.Key, value.Value); 
    }

    // Copy the DataTokens from the Route to the RouteData 
    if (DataTokens != null) {
        foreach (var prop in DataTokens) { 
            routeData.DataTokens[prop.Key] = prop.Value;
        }
    }

    return routeData;
} 

public string Url {
    get { 
        return _url ?? String.Empty; 
    }
    set { 
        // The parser will throw for invalid routes. We don't have to worry
        // about _parsedRoute getting out of sync with _url since the latter
        // won't get set unless we can parse the route.
        _parsedRoute = RouteParser.Parse(value); 

        // If we passed the parsing stage, save the original URL value 
        _url = value; 
    }
} 

When the Url is set for a route, a _parsedRoute is created based on the Url, the _parseRoute is used to match the request url with the help of default values. Then the constraint is applied. If match is found, the RouteData can be returned. Before that DataTokens is copied to RouteData as well. DataToken is not actually used in the process of matching, we can think of DataToken is some predefined RouteData. RouteCollection has another use , to generate url based on routes. When search RouteData, constraints are also tested. Normally, it is an regular expression, but you can roll out your customized constraints, here is an article about this.

//route collection member
public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
    requestContext = GetRequestContext(requestContext); 

    // Go through all the configured routes and find the first one that returns a match 
    using (GetReadLock()) { 
        foreach (RouteBase route in this) {
            VirtualPathData vpd = route.GetVirtualPath(requestContext, values); 
            if (vpd != null) {
                vpd.VirtualPath = GetUrlWithApplicationPath(requestContext, vpd.VirtualPath);
                return vpd;
            } 
        }
    } 

    return null;
} 

public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values) {
    requestContext = GetRequestContext(requestContext);

    if (!String.IsNullOrEmpty(name)) {
        RouteBase namedRoute; 
        bool routeFound; 
        using (GetReadLock()) {
            routeFound = _namedMap.TryGetValue(name, out namedRoute); 
        }
        if (routeFound) {
            VirtualPathData vpd = namedRoute.GetVirtualPath(requestContext, values);
            if (vpd != null) { 
                vpd.VirtualPath = GetUrlWithApplicationPath(requestContext, vpd.VirtualPath);
                return vpd; 
            } 
            return null;
        } 
        else {
            throw new ArgumentException(
                String.Format(
                    CultureInfo.CurrentUICulture, 
                    RoutingResources.RouteCollection_NameNotFound,
                    name), 
                "name"); 
        }
    } 
    else {
        return GetVirtualPath(requestContext, values);
    }
} 

You can choose a named route or use all routes to build a url. It delegate build url to Route.GetVirtualPath method

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
    // Try to generate a URL that represents the values passed in based on current 
    // values from the RouteData and new values using the specified Route.

    BoundUrl result = _parsedRoute.Bind(requestContext.RouteData.Values, values, Defaults, Constraints);

    if (result == null) {
        return null; 
    } 

    // Verify that the route matches the validation rules 
    if (!ProcessConstraints(requestContext.HttpContext, result.Values, RouteDirection.UrlGeneration)) {
        return null;
    }

    VirtualPathData vpd = new VirtualPathData(this, result.Url);

    // Add the DataTokens from the Route to the VirtualPathData 
    if (DataTokens != null) {
        foreach (var prop in DataTokens) { 
            vpd.DataTokens[prop.Key] = prop.Value;
        }
    }
    return vpd; 
}

Route is importaint object, it is used in url generation. It has Constraints, DataTokens, Defaults properties.

Nov 10, 2009

HttpContextBase.Items

When you using controller, you can easily access HttpContext property, which is not an System.Web.HttpContext, but a HttpContextBase object. This object has a handy Items dictionary, which can allowed you share data over a the whole request.

TempData of Controller

TempData is property of Controller. The TempData is used to save the state from page redirected from to the page redirected. So let say, your request is handled by controller1.method1, for some reason, it should be redirected to controller2.method2. Before the redirection take place, you can save some data in the TempData, then http status code 302 and new url are returned to browser, and browser make a new request using new url. In the new action method, the TempData can be restored. This behavior is showed in the following code in the Controller

//Controller member
protected override void ExecuteCore() {
    TempData.Load(ControllerContext, TempDataProvider);

    try {
        string actionName = RouteData.GetRequiredString("action");
        if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) {
            HandleUnknownAction(actionName);
        }
    }
    finally {
        TempData.Save(ControllerContext, TempDataProvider);
    }
}

This piece of code does not show how data is actually load and save, the job is actually performed by TempDataProvider. And the default provider is SessionStateTempDataProvider. We can override this TempDataProvider by injecting this property using custom ControllerFactory.

//Controller member
public ITempDataProvider TempDataProvider {
    get {
        if (_tempDataProvider == null) {
            _tempDataProvider = new SessionStateTempDataProvider();
        }
        return _tempDataProvider;
    }
    set {
        _tempDataProvider = value;
    }
}

//TempDataDictionary members
public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider) {
    IDictionary<string, object> providerDictionary = tempDataProvider.LoadTempData(controllerContext);
    _data = (providerDictionary != null) ? new Dictionary<string, object>(providerDictionary, StringComparer.OrdinalIgnoreCase) :
        new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
    _initialKeys = new HashSet<string>(_data.Keys);
    _modifiedKeys.Clear();
}

public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider) {
   //this is very important, if there is no modified, we don't need to save it
   //for next use 
   if (_modifiedKeys.Count > 0) {

        // Apply change tracking.
        foreach (string x in _initialKeys) {
            if (!_modifiedKeys.Contains(x)) {
                _data.Remove(x);
            }
        }

        // Store the dictionary
        tempDataProvider.SaveTempData(controllerContext, _data);
    }
}

public class SessionStateTempDataProvider : ITempDataProvider {
    internal const string TempDataSessionStateKey = "__ControllerTempData";

    public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext) {
        HttpContextBase httpContext = controllerContext.HttpContext;
        
        if (httpContext.Session == null) {
            throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
        }

        Dictionary<string, object> tempDataDictionary = httpContext.Session[TempDataSessionStateKey] as Dictionary<string, object>;

        if (tempDataDictionary != null) {
            // If we got it from Session, remove it so that no other request gets it
            httpContext.Session.Remove(TempDataSessionStateKey);
            return tempDataDictionary;
        }
        else {
            return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        }
    }

    public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values) {
        HttpContextBase httpContext = controllerContext.HttpContext;

        if (httpContext.Session == null) {
            throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
        }

        httpContext.Session[TempDataSessionStateKey] = values;
    }        
}

Extension point in asp.net mvc

  1. Extending route.

    Route matching is first step mvc framework, we can customize how route is matched by adding constraint, and default, and dataToken. We can implement IRouteConstraint. Here is ASP.NET MVC Tip #30 – Create Custom Route Constraints

  2. Extending IRouteHandler

    When we register route, by default the route handler is MvcRouteHandler. We can create a class implmenting IRouteHandler, of we can sub class MvcRouteHandler

  3. Exending MvcHandler

    MvcHandler is IHttpHandler, we can substitute with a MvcHandler sub class, or a complete new IHttpHandler , or override MvcHandler's ProcessRequest method. We can override ProcessRequest(HttpContextBase httpContext) method.

  4. Extending ControllerFactory and Controller. We can decide how a controller is created. A dummy example is as follow. But you can create a controller by using IoC container.

    ControllerBuilder.Current.SetControllerFactory(new ObjectControllerFactory());
    
    public class ObjectControllerFactory:DefaultControllerFactory
    {
    
        public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            if (controllerName.ToLower() == "object")
            {
                return new ObjectController(new object());
            }
            else
            {
                return base.CreateController(requestContext, controllerName);
            }
        }
    
    }
    
  5. Extending the ActionResult.

  6. Extending the Controller.

  7. Extending ModelBinder

  8. Extending ViewResult

  9. Extending ViewEngine, and IView

    We can subclass the default WebFormViewEngine, or implement and IViewEngine. The interesting method is FindView and FindPartialView.

  10. Extending ViewPage or ViewUserControl

  11. Extending HtmlHelper by adding HtmlHelper extension method.

How a view is found

There are some confusing names here. ViewResult is kind of ActionResult. It is return by an object of Controller class. ViewResult uses VewEngineCollection, a collection of IViewEngine, to find a ViewEngineResult. ViewEngineResult may or may not contain an IView. IView is implemented by ViewPage, ViewUserControl.

After a action result is returned from the action method, if it is ViewResult. The render method will find an ViewEngineResult through ViewEngineCollection object. The following code show how ViewEngineCollection finds ViewEngineResult, ViewEngineCollection enumerate all the ViewEngine to fine ViewEngineResult.

//ViewEngineCollection member
private ViewEngineResult Find(Func<IViewEngine, ViewEngineResult> cacheLocator, Func<IViewEngine, ViewEngineResult> locator) {
    ViewEngineResult result;

    foreach (IViewEngine engine in Items) {
        if (engine != null) {
            result = cacheLocator(engine);

            if (result.View != null) {
                return result; //With IView
            }
        }
    }

    List<string> searched = new List<string>();

    foreach (IViewEngine engine in Items) {
        if (engine != null) {
            result = locator(engine);

            if (result.View != null) {
                return result; //With IView
            }

            searched.AddRange(result.SearchedLocations);
        }
    }
    //a ViewEngineResult with no IView
    return new ViewEngineResult(searched);
}

If the ViewEngineResult return by by IViewEngine has an IView object, it will be returned immediately, it will be returned immediately to the ViewResult caller. If you want to use your special IView object, you need to add IViewEngine to locate your IView. If there is no ViewEngineResult with an IView is found, return new ViewEngineResult with no IView to caller ViewResult, let see how ViewResult handle this.

protected override ViewEngineResult FindView(ControllerContext context) {
    ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);
    if (result.View != null) {
        return result;
    }

    // we need to generate an exception containing all the locations we searched
    StringBuilder locationsText = new StringBuilder();
    foreach (string location in result.SearchedLocations) {
        locationsText.AppendLine();
        locationsText.Append(location);
    }
    throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
        MvcResources.Common_ViewNotFound, ViewName, locationsText));
}

It throw an exception. If a ViewEngineResult with IView is returned, ViewResult will render the IView.

//ViewResultBase member
public override void ExecuteResult(ControllerContext context) {
    if (context == null) {
        throw new ArgumentNullException("context");
    }
    if (String.IsNullOrEmpty(ViewName)) {
        ViewName = context.RouteData.GetRequiredString("action");
    }

    ViewEngineResult result = null;

    if (View == null) {
        result = FindView(context);
        View = result.View;
    }

    ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
    View.Render(viewContext, context.HttpContext.Response.Output);

    if (result != null) {
        result.ViewEngine.ReleaseView(context, View);
    }
}

Here is example to how to implement an IView.

public class StaticView : IView
{

    public void Render(ViewContext viewContext, System.IO.TextWriter writer)
    {
        writer.Write("

Hello world

"); } } public class StaticViewEngine : IViewEngine { public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { ViewEngineResult result = new ViewEngineResult(new StaticView(), this); return result; } public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { ViewEngineResult result = new ViewEngineResult(new StaticView(), this); return result; } public void ReleaseView(ControllerContext controllerContext, IView view) { //do nothing } } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); ViewEngines.Engines.Insert(0, new StaticViewEngine()); }

Nov 9, 2009

Context data in asp.net mvc

Along the asp.net mvc stack, there are lots context data being passing around. The first context data is passed into MvcRouteHandler by the System.Web.Routing.UrlRoutingModule.

public class RequestContext
{
    public RequestContext(HttpContextBase httpContext, RouteData routeData);

    public HttpContextBase HttpContext { get; }
    public RouteData RouteData { get; }
}

Then the RequestContext is passed into MvcHandler via constructor. When MvcHandler.ProcessRequest is called, it wrap the httpContext into HttpContextBase, which is System.Web.Abstractions class. The reason to use HttpContext to replace the dependency on HttpContext object, which is sealed, with dependency on HttpContextBase which is an abstraction.

//MvcHandler member
public MvcHandler(RequestContext requestContext) {
    if (requestContext == null) {
        throw new ArgumentNullException("requestContext");
    }
    RequestContext = requestContext;
}

protected virtual void ProcessRequest(HttpContext httpContext) {
    HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);
    ProcessRequest(iHttpContext);
}

protected internal virtual void ProcessRequest(HttpContextBase httpContext) {
 //skip
 IController controller = factory.CreateController(RequestContext, controllerName);
 //skip
  controller.Execute(RequestContext);
}

When creating Controller, the RequestContext is passed into the ControllerFactory.CreateController method, after the controller is created the RequestContext is passed into controller.Execute method. By default, the controller is a System.Web.Mvc.Controller. A ControllerContext is created based on the RequestContext, the controller itself. A UrlHelper is also created with RequestContext. So nowt the Controller has a ControllerContext, and UrlHelper.

//Controller member
protected override void Initialize(RequestContext requestContext) {
    base.Initialize(requestContext);
    Url = new UrlHelper(requestContext);
}
//ControllerBase member
protected virtual void Initialize(RequestContext requestContext) {
    ControllerContext = new ControllerContext(requestContext, this);
}

Then ControllerContext is used to create ControllerDescriptor, and ActionDescriptor, and FilterInfo(Filters), AuthorizationContext, parameters for actio method. ActionExecutedContext. It is also used in InvokeActionResultWithFilters method. Eventually, ActionResult use ControllerContext to ExecuteResult. ContextController is used to find ViewEngineResult

public abstract class ActionResult {

    public abstract void ExecuteResult(ControllerContext context);

}

A ViewContext is created by using ControllerContext, and IView use viewContext to render view. ViewContext.ViewData is passed into ViewPage or ViewUserControl

acton parameters

The asp.net mvc framework matches action parameters in the following order:

  1. Form values
  2. Route arguments
  3. Querystring parameters

The parameters that is passed in the action method is handled by ControllerActionInvoker.The ControllerActionInvoker tries to using reflection and other techniques to extract information for client's request, as the source code shows below.

//ControllerActionInvoker members
public bool InvokeAction(ControllerContext controllerContext, string actionName)
{
//..code skip
IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
//..
}
protected virtual IDictionary<string, object> GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
    Dictionary<string, object> parametersDict = new Dictionary(StringComparer.OrdinalIgnoreCase);
    ParameterDescriptor[] parameterDescriptors = actionDescriptor.GetParameters();

    foreach (ParameterDescriptor parameterDescriptor in parameterDescriptors)
    {
        parametersDict[parameterDescriptor.ParameterName] = GetParameterValue(controllerContext, parameterDescriptor);
    }
    return parametersDict;
}

protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
    // collect all of the necessary binding properties
    Type parameterType = parameterDescriptor.ParameterType;
    //you can register your binder, but default is DefaultModelBinder
    IModelBinder binder = GetModelBinder(parameterDescriptor);
    IDictionary<string, ValueProviderResult> valueProvider = controllerContext.Controller.ValueProvider;
    string parameterName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
    Predicate<string> propertyFilter = GetPropertyFilter(parameterDescriptor);

    // finally, call into the binder
    ModelBindingContext bindingContext = new ModelBindingContext()
    {
        FallbackToEmptyPrefix = (parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefix not specified
        ModelName = parameterName,
        ModelState = controllerContext.Controller.ViewData.ModelState,
        ModelType = parameterType,
        PropertyFilter = propertyFilter,
        ValueProvider = valueProvider
    };
    object result = binder.BindModel(controllerContext, bindingContext);
    return result;
}

You can also register your ModelBinder to help mvc to build your parameter in the application startup like the code below.

public class ConferenceModelBinder : DefaultModelBinder
{
 private readonly IConferenceRepository _repository;

 //We can require dependencies in binders just like normal classes
 public ConferenceModelBinder(IConferenceRepository repository)
 {
  _repository = repository;
 }

 public override object BindModel(ControllerContext controllerContext,
                                  ModelBindingContext bindingContext)
 {
  //first, we get the value from the request that matches the name
  ValueProviderResult providerResult =
   bindingContext.ValueProvider[bindingContext.ModelName];

  //next we use our repository to find the Conference by the key
  Conference conference = _repository.GetByKey(providerResult.AttemptedValue);
  return conference;
 }
}

ModelBinders.Binders.Add(typeof (Conference),
new ConferenceModelBinder(
new ConferenceRepositoryStub()));

Nov 8, 2009

The options to render a partial view

Normally you can do this,

<% Html.RenderPartial("LogOnUserControl"); %>

Or you can do this

ViewResult partialResult = View("next");
return View(partialResult);
<%ViewData.Model.ExecuteResult(ViewContext); %>

Nov 6, 2009

asp.net mvc request walkthrough

ASP.NET MVC request begin with a UrlRoutingModule. This component is not actually part of the System.Web.Mvc.dll, but of System.Web.Routing. You have to wire up in web.config like the following.

<httpModules>
 <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</httpModules>  

After that you can define your matching url pattern and the IRouteHandler which handle the matched url. You can add route like the following code.

Route route = new Route("{controller}/{action}/{id}", new MvcRouteHandler()) ;
route.Defaults = new RouteValueDictionary( new { controller = "Home", action = "Index", id = "" });
RouteTable.Routes.Add("Default", route);

Of course, you can add the use the extension method define in System.Web.Mvc.RouteCollectionExtensions. You can add a route with your own IRouteHandler. The purpose of IRouteHandler is very simple, to create a IHttpHandler.

public class MvcRouteHandler : IRouteHandler {
    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
        return new MvcHandler(requestContext);
    }

    #region IRouteHandler Members
    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
        return GetHttpHandler(requestContext);
    }
    #endregion
}

The RequestContext object is interesting object.It contains a HttpContextBase object and a RouteData object.This object will be used through out the mvc stack. You can also change the mvc behavior by subclassing the MvcHandler.

protected virtual void ProcessRequest(HttpContext httpContext) {
    HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);
    ProcessRequest(iHttpContext);
}

protected internal virtual void ProcessRequest(HttpContextBase httpContext) {
    AddVersionHeader(httpContext);

    // Get the controller type
    string controllerName = RequestContext.RouteData.GetRequiredString("controller");

    // Instantiate the controller and call Execute
    IControllerFactory factory = ControllerBuilder.GetControllerFactory();
    IController controller = factory.CreateController(RequestContext, controllerName);
    if (controller == null) {
        throw new InvalidOperationException(
            String.Format(
                CultureInfo.CurrentUICulture,
                MvcResources.ControllerBuilder_FactoryReturnedNull,
                factory.GetType(),
                controllerName));
    }
    try {
        controller.Execute(RequestContext);
    }
    finally {
        factory.ReleaseController(controller);
    }
}

The IControllerFactory by default is DefaultControllerFactory. This can be changed in the application_startup method. The _factoryThunk is an Func delegate. ControllerFactory is used to build a controller. Sometimes, you need to use IoC to inject dependency to into the container, if so you need to create your ControllerFactory.

ControllerBuilder.Current.SetControllerFactory(new 
StructureMapControllerFactory());

public class ControllerBuilder {
 //.. other members
public void SetControllerFactory(IControllerFactory controllerFactory) {
    if (controllerFactory == null) {
        throw new ArgumentNullException("controllerFactory");
    }

    _factoryThunk = () => controllerFactory;
}

public void SetControllerFactory(Type controllerFactoryType) {
    if (controllerFactoryType == null) {
        throw new ArgumentNullException("controllerFactoryType");
    }
    if (!typeof(IControllerFactory).IsAssignableFrom(controllerFactoryType)) {
        throw new ArgumentException(
            String.Format(
                CultureInfo.CurrentUICulture,
                MvcResources.ControllerBuilder_MissingIControllerFactory,
                controllerFactoryType),
            "controllerFactoryType");
    }

    _factoryThunk = delegate() {
        try {
            return (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
        }
        catch (Exception ex) {
            throw new InvalidOperationException(
                String.Format(
                    CultureInfo.CurrentUICulture,
                    MvcResources.ControllerBuilder_ErrorCreatingControllerFactory,
                    controllerFactoryType),
                ex);
        }
    };
}

}

The most commonly used controller is System.Web.Mvc.Controller, which inherit ControllerBase class. It has a property ControllerContext, which holds a RequestContext object, and a reference the Controller itself. MvcHandler will call the controller's Execute(RequestContext) method, which calls ExecuteCore method. As a developer, you need to implement your action method, the ExecuteCore method will try to call you action method.

protected override void ExecuteCore() {
    TempData.Load(ControllerContext, TempDataProvider);

    try {
        string actionName = RouteData.GetRequiredString("action");
        if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) {
            HandleUnknownAction(actionName);
        }
    }
    finally {
        TempData.Save(ControllerContext, TempDataProvider);
    }
}

public IActionInvoker ActionInvoker {
    get {
        if (_actionInvoker == null) {
            _actionInvoker = new ControllerActionInvoker();
        }
        return _actionInvoker;
    }
    set {
        _actionInvoker = value;
    }
}

The ActionInvoker is also an extension point, you can set this property when the controller is created, you can do this in your ControllerFactory. By default, it is ControllerActionInvoker. Below is the code how ControllerActionInvoker select a action method, and invoking it. This is most interesting part.

// class ControllerActionInvoker
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) {
    if (controllerContext == null) {
        throw new ArgumentNullException("controllerContext");
    }
    if (String.IsNullOrEmpty(actionName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
    }
    //this will return ReflectedControllerDescriptor, which is used to expose
   //some meta of the controller, which implement System.Reflection.ICustomAttributeProvider
    ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
    //Use controllerDescriptor build a ActionDescripter which is a ReflectedActionDescriptor, which also implements ICustomAttributeProvider
    ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
    if (actionDescriptor != null) {
        //FilterInfo has four list,ActionFilters(IActionFilter), AuthorizationFilters(IAuthorizationFilter), ExceptionFilters(IExceptionFilter), ResultFilters(IResultFilter), these list contains FilterAttribute, but also the controller itself, because Controller implements  IActionFilter, IAuthorizationFilter, IExceptionFilter, IResultFilter
        FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);

        try {
            AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
            if (authContext.Result != null) {
                // the auth filter signaled that we should let it short-circuit the request
                InvokeActionResult(controllerContext, authContext.Result);
            }
            else {
                if (controllerContext.Controller.ValidateRequest) {
                    ValidateRequest(controllerContext.HttpContext.Request);
                }
                //parameters can build from controllerContext, and will be feed to actionMethod later.
                IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                //your action method will be executed, and ActionResult will be 
                //returned here, which normally is ViewResult
                ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
                //the ActionExecutedContext.Result will be examined, if it is ActionResult, it will be invoked to render a view
                InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
            }
        }
        catch (ThreadAbortException) {
            // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
            // the filters don't see this as an error.
            throw;
        }
        catch (Exception ex) {
            // something blew up, so execute the exception filters
            ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
            if (!exceptionContext.ExceptionHandled) {
                throw;
            }
            InvokeActionResult(controllerContext, exceptionContext.Result);
        }

        return true;
    }
    // notify controller that no method matched
    return false;
}

There are lots implementation details here, I am going to skip most of them here. And focus on how a view is rendered. When ActionResult is returned from the method call InvokeActionMethodWithFilters, it will be passed in the method InvokeActionResultWithFilters, that is the beginning of rendering a view. The following code will be eventually run.

//ControllerActionInvoker member
protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
{
    actionResult.ExecuteResult(controllerContext);
}

ViewResult inherit from ViewResultBase, which inherite ActionResult. The interesting method is ExecuteResult(ControllerContext), it basically to find a view and then render the view.

//ViewResultBase member
public override void ExecuteResult(ControllerContext context) {
    if (context == null) {
        throw new ArgumentNullException("context");
    }
    if (String.IsNullOrEmpty(ViewName)) {
        ViewName = context.RouteData.GetRequiredString("action");
    }

    ViewEngineResult result = null;

    //View is property Of ViewResultBase, it is Type IView
    if (View == null) {
        result = FindView(context);
        View = result.View;
    }
    //push the ViewData, TempData into viewCotext, which is passed into View.Render()
    ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
    View.Render(viewContext, context.HttpContext.Response.Output);

    if (result != null) {
        result.ViewEngine.ReleaseView(context, View);
    }
}

public interface IView {
    void Render(ViewContext viewContext, TextWriter writer);
}

//ViewResult member
protected override ViewEngineResult FindView(ControllerContext context) {
    //ViewEngineCollection
    ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);
    if (result.View != null) {
        return result;
    }

    // we need to generate an exception containing all the locations we searched
    StringBuilder locationsText = new StringBuilder();
    foreach (string location in result.SearchedLocations) {
        locationsText.AppendLine();
        locationsText.Append(location);
    }
    throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
        MvcResources.Common_ViewNotFound, ViewName, locationsText));
}

//ViewResultBase member, this is an extension point
//we can add our ViewEngine here.
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
    Justification = "This entire type is meant to be mutable.")]
public ViewEngineCollection ViewEngineCollection {
    get {
        return _viewEngineCollection ?? ViewEngines.Engines;
    }
    set {
        _viewEngineCollection = value;
    }
}

public static class ViewEngines {

    private readonly static ViewEngineCollection _engines = new ViewEngineCollection {
        new WebFormViewEngine() 
    };

    public static ViewEngineCollection Engines {
        get {
            return _engines;
        }
    }
}

We can see here, to find a view, we need a ViewEngineCollection. By default this ViewEngineCollection has one IViewEngin(WebFormViewEngine). The purpose a IViewEngine is to find partial view and view, like the following. But WebFormViewEngine inherit VirtualPathProviderViewEngine, which implmenet IViewEngine. To find View, first we need to locate the Physical path of the view file(aspx or ascx), to decide whether a file exist, there is to ask a buildManager to build an instance of it. Physical path searhing follow a couple of pattern, if the view file can not be located. Then an exeption will be throw. If found a the path will be cached for next probing.

public interface IViewEngine {
    ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
    ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
    void ReleaseView(ControllerContext controllerContext, IView view);
}

//VirtualPathProviderViewEngine member
public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
    if (controllerContext == null) {
        throw new ArgumentNullException("controllerContext");
    }
    if (String.IsNullOrEmpty(viewName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
    }

    string[] viewLocationsSearched;
    string[] masterLocationsSearched;

    string controllerName = controllerContext.RouteData.GetRequiredString("controller");
    string viewPath = GetPath(controllerContext, ViewLocationFormats, "ViewLocationFormats", viewName, controllerName, _cacheKeyPrefix_View, useCache, out viewLocationsSearched);
    string masterPath = GetPath(controllerContext, MasterLocationFormats, "MasterLocationFormats", masterName, controllerName, _cacheKeyPrefix_Master, useCache, out masterLocationsSearched);

    if (String.IsNullOrEmpty(viewPath) || (String.IsNullOrEmpty(masterPath) && !String.IsNullOrEmpty(masterName))) {
        return new ViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched));
    }

    return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
}


//WebFormViewEngine constructor
public WebFormViewEngine() {
    MasterLocationFormats = new[] {
        "~/Views/{1}/{0}.master",
        "~/Views/Shared/{0}.master"
    };

    ViewLocationFormats = new[] {
        "~/Views/{1}/{0}.aspx",
        "~/Views/{1}/{0}.ascx",
        "~/Views/Shared/{0}.aspx",
        "~/Views/Shared/{0}.ascx"
    };

    PartialViewLocationFormats = ViewLocationFormats;
}

The WebFormViewEngine defines how to create view, it implement two abstract method of VirtualPathProviderViewEngine.

protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) {
    return new WebFormView(partialPath, null);
}

protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) {
    return new WebFormView(viewPath, masterPath);
}

The WebFormView use tranditional aspx ViewPage or ViewUserControl ascx to render view.

//WebFormView  members
public virtual void Render(ViewContext viewContext, TextWriter writer) {
    if (viewContext == null) {
        throw new ArgumentNullException("viewContext");
    }
    
    //viewInstance is an instance of ViewPage(aspx or ascx)
    object viewInstance = BuildManager.CreateInstanceFromVirtualPath(ViewPath, typeof(object));
    if (viewInstance == null) {
        throw new InvalidOperationException(
            String.Format(
                CultureInfo.CurrentUICulture,
                MvcResources.WebFormViewEngine_ViewCouldNotBeCreated,
                ViewPath));
    }


    ViewPage viewPage = viewInstance as ViewPage;
    if (viewPage != null) {
        RenderViewPage(viewContext, viewPage);
        return;
    }
    //we can see that viewInstance does not necessary to be a ViewPage, it can be ViewUserControl as well
    ViewUserControl viewUserControl = viewInstance as ViewUserControl;
    if (viewUserControl != null) {
        RenderViewUserControl(viewContext, viewUserControl);
        return;
    }

    throw new InvalidOperationException(
        String.Format(
            CultureInfo.CurrentUICulture,
            MvcResources.WebFormViewEngine_WrongViewBase,
            ViewPath));
}

private void RenderViewPage(ViewContext context, ViewPage page) {
    if (!String.IsNullOrEmpty(MasterPath)) {
        page.MasterLocation = MasterPath;
    }
    //passed in ViewData to aspx or ascx
    page.ViewData = context.ViewData;
    page.RenderView(context);
}

private void RenderViewUserControl(ViewContext context, ViewUserControl control) {
    if (!String.IsNullOrEmpty(MasterPath)) {
        throw new InvalidOperationException(MvcResources.WebFormViewEngine_UserControlCannotHaveMaster);
    }

    //passed in ViewData to aspx or ascx
    control.ViewData = context.ViewData;
    control.RenderView(context);
}

To render a ViewPage, firstly, it initialized three very handy object will be used extensively in the aspx or ascx, they are Ajax(AjaxHelper), Html(HtmlHelper),Url(UrlHelper). Then it delegate the control to ProcessRequest method of Page class.

//public class ViewPage : Page, IViewDataContainer
public virtual void RenderView(ViewContext viewContext) {
    ViewContext = viewContext;
    InitHelpers();
    // Tracing requires Page IDs to be unique.
    ID = Guid.NewGuid().ToString();
    ProcessRequest(HttpContext.Current);
}


public virtual void InitHelpers() {
    Ajax = new AjaxHelper(ViewContext, this);
    Html = new HtmlHelper(ViewContext, this);
    Url = new UrlHelper(ViewContext.RequestContext);
}

HtmlHelper is responsible to render partial view.

internal virtual void RenderPartialInternal(string partialViewName, ViewDataDictionary viewData, object model, ViewEngineCollection viewEngineCollection) {
    if (String.IsNullOrEmpty(partialViewName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "partialViewName");
    }
    
    //a new copy a ViewData is created 
    ViewDataDictionary newViewData = null;

    if (model == null) {
        if (viewData == null) {
            newViewData = new ViewDataDictionary(ViewData);
        }
        else {
            newViewData = new ViewDataDictionary(viewData);
        }
    }
    else {
        if (viewData == null) {
            newViewData = new ViewDataDictionary(model);
        }
        else {
            newViewData = new ViewDataDictionary(viewData) { Model = model };
        }
    }
    //a newViewContext is created, not shared with passed in data
    ViewContext newViewContext = new ViewContext(ViewContext, ViewContext.View, newViewData, ViewContext.TempData);
    //use the passed in viewEngineCollectio to newViewContext to find a partial view
    IView view = FindPartialView(newViewContext, partialViewName, viewEngineCollection);
    view.Render(newViewContext, ViewContext.HttpContext.Response.Output);
}

//ViewDataDictionary member
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
    Justification = "See note on SetModel() method.")]
public ViewDataDictionary(ViewDataDictionary dictionary) {
    if (dictionary == null) {
        throw new ArgumentNullException("dictionary");
    }

    foreach (var entry in dictionary) {
        _innerDictionary.Add(entry.Key, entry.Value);
    }
    foreach (var entry in dictionary.ModelState) {
        ModelState.Add(entry.Key, entry.Value);
    }
    Model = dictionary.Model;
}

Nov 1, 2009

Semantics works?

A developer is a creativity entity. There are so many software technologies emerging everyday, many of us are struggling to keep pace with the them. I am just an average developer, and I still tirelessly studying these technologies, because programming is my passion and love. Gradually, I understand semantics is the driven force of the evolution of software tools, framework, platform, methodologies and standards. As a .net developer, I use the object-oriented programming, domain driven development, agile programing, mocking framework, asp.net mvc, css, xhtml, wpf, RESTful web service.

I truely believe that semantics works. Today I am moving my studying notes to SemanticsWorks.

Oct 23, 2009

Best practice to develop jQuery plugin

  1. Create a private scope for $
  2. Attach plugin to $.fn alias
  3. Add implicit iteration
  4. Enable chaining
  5. Add default options
  6. Add custom options
  7. global custom options
<div id="counter1">
</div>
<div id="counter2">
</div>
<script>
(function($) {
    $.fn.count = function(customOptions){

        var options = $.extend({},$.fn.count.defaultOptions, customOptions);
       
        return this.each(function(){
            var $this = $(this);
            $this.text(options.startCount);
            var myInterval = window.setInterval(function(){
                var currentCount = parseFloat($this.text());
                var newCount = currentCount+1;
                $this.text(newCount+'');
            }, 1000);
        });
       
    };
       
    $.fn.count.defaultOptions = {
        startCount:'100'
    };

})(jQuery);
 
jQuery.fn.count.defaultOptions.startCount = '300';

jQuery('#counter1').count();
jQuery('#counter2').count({startCount:'500'});
 
</script>

Oct 21, 2009

javascript reflection in jQuery

String: typeof object === "string"
Number: typeof object === "number"
Boolean: typeof object === "boolean"
Object: typeof object === "object"
Function: jQuery.isFunction(object)
Array: jQuery.isArray(object)
Element: object.nodeType
null: object === null
undefined: typeof variable === "undefined" or object.prop === undefined
null or undefined: object == null


 toString = Object.prototype.toString,
 
 //var x = { name :"fred" };
    //alert(x.hasOwnProperty("name"));
 hasOwn = Object.prototype.hasOwnProperty,

 push = Array.prototype.push,

 isFunction: function( obj ) {
  return toString.call(obj) === "[object Function]";
 },

 isArray: function( obj ) {
  return toString.call(obj) === "[object Array]";
 },

 isPlainObject: function( obj ) {
  // Must be an Object.
  // Because of IE, we also have to check the presence of the constructor property.
  // Make sure that DOM nodes and window objects don't pass through, as well
  if ( !obj || 
    toString.call(obj) !== "[object Object]" || 
    obj.nodeType || 
    obj.setInterval ) {
    
   return false;
  }
  
  // Not own constructor property must be Object
  if ( obj.constructor &&
   !hasOwn.call(obj, "constructor") &&
   !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
   return false;
  }
  
  // Own properties are enumerated firstly, so to speed up,
  // if last one is own, then all properties are own.
 
  var key;
  for ( key in obj ) {}
  
  return key === undefined || hasOwn.call( obj, key );
 },

 isEmptyObject: function( obj ) {
  for ( var name in obj ) {
   return false;
  }
  return true;
 },

isWindow: function( obj ) {
 return obj && typeof obj === "object" && "setInterval" in obj;
},

//new in jQuery 1.4
$.type(object);

Oct 17, 2009

it must be "new"ed.

The following is constructor which prevent not using "new" keyword


function User(first, last){ 
  if ( !(this instanceof arguments.callee) ) 
    return new User(first, last); 
   
  this.name = first + " " + last; 
} 

Oct 16, 2009

javascript scope

In JavaScript, {blocks} do not have scope. Only functions have scope. Vars defined in a function are not visible outside of the function.

object literal

var myObject = { name: "Jack B. Nimble", 'goto': 'Jail', grade: 'A', level: 3, "3": "three" };
alert(myObject.name);
alert(myObject["name"]);
alert(myObject["goto"]);
alert(myObject.goto); //ok
alert(myObject["3"]);
//alert(myObject.3); //error

function overload

function.length can tell you the number of parameters defined, using this we can create overload functions

function addMethod(object, name, fn){ 
  // Save a reference to the old method 
  var old = object[ name ]; 
 
  // Overwrite the method with our new one 
  object[ name ] = function(){ 
    // Check the number of incoming arguments, 
    // compared to our overloaded function 
    if ( fn.length == arguments.length ) 
      // If there was a match, run the function 
      return fn.apply( this, arguments ); 
 
    // Otherwise, fallback to the old method 
    else if ( typeof old === "function" ) 
      return old.apply( this, arguments ); 
  }; 
} 
 
function Ninjas(){ 
  var ninjas = [ "Dean Edwards", "Sam Stephenson", "Alex Russell" ]; 
  addMethod(this, "find", function(){ 
    return ninjas; 
  }); 
  addMethod(this, "find", function(name){ 
    var ret = []; 
    for ( var i = 0; i < ninjas.length; i++ ) 
      if ( ninjas[i].indexOf(name) == 0 ) 
        ret.push( ninjas[i] ); 
    return ret; 
  }); 
  addMethod(this, "find", function(first, last){ 
    var ret = []; 
    for ( var i = 0; i < ninjas.length; i++ ) 
      if ( ninjas[i] == (first + " " + last) ) 
        ret.push( ninjas[i] ); 
    return ret; 
  }); 
} 
 
var ninjas = new Ninjas(); 
assert( ninjas.find().length == 3, "Finds all ninjas" ); 
assert( ninjas.find("Sam").length == 1, "Finds ninjas by first name" ); 
assert( ninjas.find("Dean", "Edwards").length == 1, "Finds ninjas by first and last name" ); 
assert( ninjas.find("Alex", "X", "Russell") == null, "Does nothing" );

later method

Object.prototype.later = function (msec, method) {
    var context = this,
    args = Array.prototype.slice.apply(arguments, [2]); 
    if (typeof method === 'string') { 
        method = context[method]; 
    } 
    setTimeout(function () { 
        method.apply(context, args); 
    }, msec); 
    return context; 
}; 

var o = {
  name: "fred",
  greet: function (msg) {
          alert("my name is " + this.name + "," + msg);
  }
}
    
o.later(1000, function () { alert("hello");});
o.later(1000, "greet", "how are you?");
​

fixed a closure bug

Closure refer the ability that a function can access and manipulate external variable from with a function. Sometimes, this is not good because the if a function depends on the external state. When the external state changes, the function may produce unexpected result.

//this is because the function inside setTimeout refers to the i only when it is 
//executed, by then i==4, the problem is that i is external variable

for (var i = 0; i < 4; i++) {
            setTimeout(function() {
                alert(i); //it is always 4
            }, i * 1000);
    }

//the solution is make the i as local variable, so parameter is a solution, and
//self-execution

var count = 0;
for (var i = 0; i < 4; i++) {
    (function(j) {
        setTimeout(function() {
            alert(j); //it will show 0, 1, 2, 3
        }, j * 1000);
    }) (i);
}

So sometimes it is good to remove the external dependencies. The follow code is anther example.

var ninja = {
    yell: function(n) {
        return n > 0 ? arguments.callee(n - 1) + "a" : "hiy";
    }
}

/*      
this is also ok
var ninja = { yell: function x(n) {
return n > 0 ? x(n - 1) + "a" : "hiy";
}
};
*/

/*this is has bug, because ninja.yell is inside of function which depends external state
var ninja = { yell: function(n) {
return n > 0 ? ninja.yell(n - 1) + "a" : "hiy";
}
};
*/

var sumurai = { yell: ninja.yell };
ninja = null;
ok(sumurai.yell(4) == "hiyaaaa", "argumnets.collee is the function itself");

efficency string operation

Because string is immutable in JavaScript, concatenation with array.join('') is much efficient. The following code use all the chinese characters. Click here to show

      var sb = [];
        sb[sb.length] = "

"; for (var i = 0x4e00; i <= 0x9fcf; i++) { sb[sb.length] = String.fromCharCode(i); } sb[sb.length] = "

"; $("#chinese").html(sb.join("")); return false;

the bind function

John Resig has page Learning Advanced JavaScript to explain how the following script works.

// The .bind method from Prototype.js 
Function.prototype.bind = function(){ 
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); 
  return function(){ 
    return fn.apply(object, 
      args.concat(Array.prototype.slice.call(arguments))); 
  }; 
};

His explanation is wonderful. And this piece of code is simple, powerful. But it maybe still hard for anyone to understand without any explanation. So I refactored it as follow, and add one use case.

Function.prototype.bind = function() {
    var function_to_be_bound = this;
    //convert argements into a real array
    var args = Array.prototype.slice.call(arguments); 
    //the first element in the array is the context_object to be bound to
    var context_object = args.shift();
    //the rest of elements in the array is the prefilled parameter
    var binding_parameters = args;

    return function() {
        var invoking_parameters = Array.prototype.slice.call(arguments);
        var combined_parameters = binding_parameters.concat(invoking_parameters);
        var result_from_function_run_in_new_context = function_to_be_bound.apply(context_object, combined_parameters);
        return result_from_function_run_in_new_context;
    };
}

function reply_greeting(your_name) {
    //"this" is the context object
    alert("my name is " + this.name + ", Nice to meet you, " + your_name);
}

var fred = { name: "fred" };

var reply_greeting_of_fred_to_you = reply_greeting.bind(fred); 
var reply_greeting_of_fred_to_john = reply_greeting.bind(fred, "john");

reply_greeting_of_fred_to_you("jeff"); //expect: "my name is fred, Nice to meet you, jeff"
reply_greeting_of_fred_to_john(); //expect: "my name is fred, Nice to meet you, john"

Another article may help you to understand is Functional Javascript

Oct 15, 2009

memoried function

 Function.prototype.memorized = function(key) {
     this._values = this._values || {};

     if (this._values[key] !== undefined) {
         return this._values[key]
     }
     else {
         //"this" is parent function object
         this._values[key] = this.apply(this, arguments); /* the "this" passed as context object is optional? */
         return this._values[key];
     }
 };


 function isPrime(num) {
     alert(this);
     var prime = num != 1;
     for (var i = 2; i < num; i++) {
         if (num % i == 0) {
             prime = false;
             break;
         }
     }
     return prime;
 }

 var a = isPrime.memorized(5);
 alert(a);
 var b = isPrime.memorized(5);
 alert(b);



curry function

Function.method('curry', function() {
    //arguments can not be passed in to closure function
    //var l = arguments.length;
    //var args = [];
    //for (var i = 0; i < l; i++) {
    //    args[i] = arguments[i];
    //}
    var args = Array.prototype.slice.apply(arguments);
    var original_function = this;

    return function() {
        //arguments is not the external arguments
        //for (var i = 0; i < arguments.length; i++) {
        //    args[args.length] = arguments[i];
        //}
        args = args.concat(Array.prototype.slice.call(arguments));
        return original_function.apply(null, args);
    };
});

function add() {
    var sum = 0;
    for (i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}

var add1 = add.curry(1);
var s = add1(2);
alert(s);


Oct 13, 2009

Does it matter for an object to know its constructor?

We all knows that javascript inherit the functionality from its constructor. It is important to understand the concept every object has a secret link to constructor's prototype. How about constructor? Does a object know who is its constructor? Let's see a simple example

function Person() {
  alert(this.constructor.name); //Person
  this.constructor.count++; // reuse its constructor as a name space to prevent name polution
};

Person.count = 0;

var p = new Person();
alert(p.constructor == Person); //true
alert(Person.count); //1

We know that constructor is also an object, (an object is not necessarily a constructor), in our case we reuse the constructor as namespace or object. And the Id is this last count. Here Person's prototype is created by Person function automatically which is essentially an {}, an empty object, so the reflection shows that Person is the constructor of p. However, if we explicitly assign a prototype to Person function. Something strange happens

function Person() {
  alert(this.constructor.name); //Person
  this.constructor.count++; // reuse its constructor as a name space to prevent name polution
};

Person.count = 0;
Object.count = 0;
Person.prototype = {};

var p = new Person();
alert(p.constructor == Person); //false, it is Object
alert(Person.count); //0
alert(Object.count); //1

Suddenly the reflection shows, the object became constructor. Why? We need to have deeper understand how constructor works. When an object is created by using "new Person()", the Person function finds that it does has no explicit prototype, then it create one explicitly, so the refection shows that Person is the constructor. But if Person finds it has an explicit prototype, it use that prototype, and the constructor of that prototype in our case is Object, reflection mechanism report that constructor is the constructor of newly created object. According to ECMAScript Language Specification Edition 3

ECMAScript supports prototype-based inheritance. Every constructor has an associated prototype,and every object created by that constructor has an implicit reference to the prototype (called the object’s prototype) associated with its constructor.

If we don't reuse constructor as name space like Person, this is does not cause any problem. If we explicitly use Person as name space, it also solves the problem.

function Person() {
  alert(Person.name); //Person
  Person.count++;
};

However, using the syntax of p.constructor.xx give you more flexibility, we can solve the problem by just adding one line, it does not change other behaviors or add other functionality

Person.prototype.constructor = Person;

Sep 27, 2009

4 Equals, Reference Type, Value Type

The very fundamental design in .net clr is that type system is classified into two type, reference type and value type. This design decision has profound implication on the .net. One examples is to test the equality between objects.
Basically we have two kinds of comparison, identity comparison(whether two object has the same identity), semantic comparison(whether two object means the same thing, most people refer it as value equality comparison, I use "semantic" because value of reference type is a reference, even the values of reference typed variable are different, it is possible that they mean the same thing in semantics). Since we have the two different type, this makes things complicated. For example, can we compare the "value" of reference type, or can we compare the reference of value type. If there had been only reference type, if there had been no value type, the .net world will be simpler. Why we need two types? This is a deep question, lots of this topics has been covered in a book "CLR via C#". Basically, this a consideration of memory efficiency and performance. What we need to know is that the value of reference type is reference, the value of value type is value.

Reference type identity comparison

To do identity comparison for reference type, we should call Object.ReferenceEquals(objA, objB), or you can use shortcurt operator "==" like "objA == objB". The following source code shows that ReferenceEquals and == operator is the same.
public class Object 
{
   [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
   public static bool ReferenceEquals (Object objA, Object objB) {
       return objA == objB; 
   }
}

If they are the same, why we still need ReferenceEquals, this is because "==" is an operator for object type, if we are not using this method, we can use "(object)a == (object)b".
//you can use
TypeA a;
TypeB b;

Assert.IsTrue(ReferenceEquals(a, b) == ( (object)a == (object)b) );
The "==" means different things for different type value type. What exactly "==" does? For all reference type and all primitive value type, like int, double, enum, it become "ceq" instruction after it is compiled msil. What does "ceq" do? It is clr implementation question, I guess it compare identity equal for reference type and compare value equal for primitive value type. But it means "==" operator for custom value type like struct, which has not default implementation.

Reference type semantic comparison

The default semantic comparison of reference type is identity comparison, because the value of reference type variable is a reference. The default implementation is as follow.
// Returns a boolean indicating if the passed in object obj is
// Equal to this.  Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to 
// replace Equals with EqualsValue for value types).
// 
public virtual bool Equals(Object obj)
{
    return InternalEquals(this, obj);
} 

[MethodImplAttribute(MethodImplOptions.InternalCall)] 
internal static extern bool InternalEquals(Object objA, Object objB);
According the comments, for reference type object, InternalEquals just compare the reference, it does not compare referenced content. The following code shows this behavior.
static void Main(string[] args)
{
    Customer c1 = new Customer { Name = "fred" };
    Customer c2 = new Customer { Name = "fred" };
    Customer c3 = c1;
    
    Console.WriteLine(object.ReferenceEquals(c1, c2)); //False
    Console.WriteLine(object.ReferenceEquals(c1, c3));  //True
    
    Console.WriteLine(c1 == c2); //False
    Console.WriteLine(c1 == c3); //True

    Console.WriteLine(c1.Equals(c2));  //False, event the reference content is same
    Console.WriteLine(c1.Equals(c3));  //True
}

 public class Customer
 {
     public string Name { get; set; }
 }
But sometimes, we want to change this semantics. In our case, we can say if the name of customer is the same, regardless their identity. So we can override the instance Equals method like the following.
public class Customer
    {
        public string Name { get; set; }

        public override bool Equals(object obj)
        {
            var c = obj as Customer;
            if (c == null)
            {
                return false;
            }
            else
            {
                return this.Name == c.Name;
            }
        }
    }

Value type identity comparison

Can you compare identity of value type variable. "Yes". Should you compare identity of value types variable. "No". The result will always return "False", because object put in different boxes before comparison.
Console.WriteLine(object.ReferenceEquals(1, 1)); // False

Value type semantic comparison

Although you can use "==" operator with primitive value type like System.Int32, but you can not use it with custom value type such as struct before you implement the operator by your self. But you can use object type's instance Equals to do semantic comparison, which use reflection to check content equality like below.
public override bool Equals (Object obj) {
    BCLDebug.Perf(false, "ValueType::Equals is not fast.  "+this.GetType().FullName+" should override Equals(Object)"); 
    if (null==obj) { 
        return false;
    } 
    RuntimeType thisType = (RuntimeType)this.GetType();
    RuntimeType thatType = (RuntimeType)obj.GetType();

    if (thatType!=thisType) { 
        return false;
    } 

    Object thisObj = (Object)this;
    Object thisResult, thatResult; 

    // if there are no GC references in this object we can avoid reflection
    // and do a fast memcmp
    if (CanCompareBits(this)) 
        return FastEqualsCheck(thisObj, obj);

    FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 

    for (int i=0; i<thisFields.Length; i++) { 
        thisResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(thisObj,false);
        thatResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(obj, false);

        if (thisResult == null) { 
            if (thatResult != null)
                return false; 
        } 
        else
        if (!thisResult.Equals(thatResult)) { 
            return false;
        }
    }

    return true;
} 
Because the method use reflection to compare, it tends to be slow. So we should always override instance Equals() for your custom value type struct to improve performance.

Comparing objects of unknown type

If we don't know the types of two object, the best bet is to use static method object.Equals(objA, objB). This method check if the identity equal first, then check semantic equality, this if This method is as follow.
public static bool Equals(Object objA, Object objB)
{
    if (objA==objB) {
        return true;
    } 
    if (objA==null || objB==null) {
        return false; 
    } 
    return objA.Equals(objB);
} 
To wrap it, what does this means to me? We can follow the following pseudo code
if (we compare two object of the same type)
{
    if (type is reference type)
    {

        if (we want semantic compare && we have override the objA.Eqauls method)
        {
            objA.Equals(B); 
        }
        else //we just want to identity compare
        {
            always use "objA == objB";
            but object.ReferneceEqual(objA, objB) and objA.Eqauls(objB) do the same thing in this case
        }
    }
    else //type is value type
    {
        if (we want identity compare)
        {
           forget about it, although we can call object.ReferenceEqual(objA, objB)
            it will always return false because of boxing
        }
        else //we should always use semantic compare
        {
            if (type is primitive value type like int)
            {
                x == y // it is compiled to ceq il instruction
            }
            else
            {
                if (you have implment the == operator for this type)
                {
                    use objA == objB
                }
                else
                {
                    use objA.Equels(objB)
                    //if you want more efficent comparison override instece Equals method
                }
            }
        }
    }
}
else //we compare two object of unknown type
 {
    Object.Equals(objA, objB);
 }
For reference type, "==" is enough for a situation, unless you want to change the default semantics comparison. For primitive value type, "==" is enough for most situations. For struct, you are encourage to override default semantics comparison obj.Equals() for performance, although not mandatory, and use obj.Equals for comparison.

Sep 26, 2009

IEnumberable, IQueryable , Lambda expression - part2

I have seen such following piece of code written by a developer from a client.

interface IContactRepository
{
    IEnumberable<contact> GetSomeContacts();
}

class ContactRepository : IContactRepository
{
   public IEnumerable<contact> GetSomeContacts()
   {
      //query is linq to sql query object
      IQueryable<contact> query = ...
      return query;
    }
}

Is it a better choice to using IEnumerable<t> instead of IQueryable<t>. I guess his concerns is that, if the interface is too specific, first this may give client more functionality than is required, second this may limit the server's choice of implementation. In lots case, this concern is right, we should give client the only functionality which client needs, nothing less and nothing more, and server should has more freedom to implement.

interface IPerson 
{
   void Eat();
   void Sleep();
}

interface ISales : IPerson
{
    void Sell();
}

interface ITeacher : IPerson
{
    void Teache();
}

class Service
{
     //Unappropriate
//     public ISales  GetPerson()
//     {
//            return ...
//     }

     //better
     public IPerson GetPerson()
     {
            return ...
     }

}

Firstly, if the method return a ISales, First client will have one extra unnecessary method Sell. Secondly If the client only needs a IPerson, and the contract says client needs a IWorker, this will limit server's ability to serve the client, for example, server can not return a ITeacher.

Is this design guideline also applicable to the case of IContactRepository.

public interface IQueryable<t> : IEnumerable<t>, IQueryable, IEnumerable 
{} 
 
public interface IQueryable : IEnumerable 
{ 
        Type ElementType { get; } 
        Expression Expression { get; } 
        IQueryProvider Provider { get; } 
} 

First the the IQuerable<t> interface does give user more functionality than the IEnunumerable<t>, but these members are read only, and client can not use them directly for query. Because the query functionality comes from the static method in Enumerable and Queryable, but not the IQuerable<t>, and IEnumeralbe<t>, from the client's perspective, Two interfaces works identically. Secondly, the interface does limit limit server's implementation choice, because server cannot return a IEnumberable<t> . Initially, I thought I can implement easily a empty IQueryable<t> that wrap a IEnumberable<t>. It turns out to be even easier. Because the Enumerable already implement an static method AsQueryable() for you, the Linq team in Microsoft already expect this is a common use case. So all you need to do is call the method can you IEnumberable&lgt;T> will become IQueryable<t>. like the following.

int[] intEnumerable = { 1, 2, 3 , 5};
IQueryable intQuery = intEnumerable.AsQueryable().Where( number => number > 2);
foreach (var item in intQuery)
{
    Console.WriteLine(item);
}
Console.WriteLine(intQuery.GetType().ToString()); //System.Linq.EnumerableQuery`1[System.Int32]

//code decompiled by reflector
  ParameterExpression CS$0$0000;
    IQueryable intQuery = new int[] { 1, 2, 3, 5 }.AsQueryable<int>().Where<int>(Expression.Lambda<Func<int, bool>>(Expression.GreaterThan(CS$0$0000 = Expression.Parameter(typeof(int), "number"), Expression.Constant(2, typeof(int))), new ParameterExpression[] { CS$0$0000 }));
    foreach (object item in intQuery)
    {
        Console.WriteLine(item);
    }
    Console.WriteLine(intQuery.GetType().ToString());


So a it seems be a better to replace IEnumberable<t> with IQueryable<t>. As for as the interface concerns, the replacement does not give client any exactly same query experience and it is more difficult to implement. A great benefit of this replacement is the performance, using IEnumberable<t> will be much slower than IQuerable<t>. Consider the following code, the Where method for IQueryable<t> will treat the lambda expression as expression tree and query will be executed at server side which is much faster, while the IEnumerable<t> will treat the lambda expression as delegate and query will be executed at client side, which will be slower. Consider the following code.

var thisContact = contaceRepository. GetSomeContacts().Where( ctc => ctc.Id = 1).First();

Linq provide us a new way to design our domain model. In the post Extending the World, author says

Typically for a given problem, a programmer is accustomed to building up a solution until it finally meets the requirements. Now, it is possible to extend the world to meet the solution instead of solely just building up until we get to it. That library doesn't provide what you need, just extend the library to meet your needs.

It is very important to build extensible domain model by taking the advantage of IQueryable<t> interface. Using IEnumberable<t> only will hit the performance very seriously. The only pitfall to user IQueryable<t> is that user may send unnecessary complex to the server, but this can be resolved by designing the method so that only appropriate IQueryable<t> is returned, for example return GetSome instead of GetAll. Another solution is adding a view model which return a IEnumberable<t>

IEnumberable, IQueryable , Lambda expression - part1

When we type the following code

IEnumerable<int> intEnumerable = null;
var q1 = intEnumerable.Where( x => x > 10);

we know that Where method is not part of the IEnumberable<t> interface or IEnumberable interface, it comes from extension method of Enumerable, which is static class and it has no inheritance relation With IEnumerable or IEnumberable<t>. The power of Linq-To-Object does not come from IEnumberable or IEnumberable<t> or its implemenation, it comes from the extension method. Let's take a look what does the extension method do? Using Reflector we get the following source code.


public static class Enumerable
{
public static IEnumerable<tsource> Where<tsource>(this IEnumerable<tsource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    if (source is Iterator<tsource>)
    {
        return ((Iterator<tsource>) source).Where(predicate);
    }
    if (source is TSource[])
    {
        return new WhereArrayIterator<tsource>((TSource[]) source, predicate);
    }
    if (source is List<tsource>)
    {
        return new WhereListIterator<tsource>((List<tsource>) source, predicate);
    }
    return new WhereEnumerableIterator<tsource>(source, predicate);
}
}

We can see there , the delegate passed in to the method is the code that does the filtering.

IQueryable<t> inherit from IEnumerable. But what extra value does the IQueryable bring. Let's take a look of the following code. and the code it generated by c# compiler.

public interface IQueryable<t> : IEnumerable<t>, IQueryable, IEnumerable
{}

public interface IQueryable : IEnumerable
{
        Type ElementType { get; }
        Expression Expression { get; }
        IQueryProvider Provider { get; }
}

It does not tell too much? Let's move on an querable example and decomplie to see what it does.

IQueryable<int> intQuerable = null;
var q2 = intQuerable.Where(x => x > 10);

// decomplied by reflector
ParameterExpression CS$0$0000;
IQueryable<int> q2 = intQuerable.Where<int>(Expression.Lambda<Func<int, bool>>(Expression.GreaterThan(CS$0$0000 = Expression.Parameter(typeof(int), "x"), Expression.Constant(10, typeof(int))), new ParameterExpression[] { CS$0$0000 }));

From this example, we can see that the Lamda Expression is not converted to a delegate, but to an expression tree. But why the extension method Enumerable.Where(IEnumerable Where(this IEnumerable source, Func predicate) is not used? It turns out that, the c# compiler pick a more a suitable extension from Queryable. Here is the code from Reflector.

public static IQueryable<tsource> Where<tsource>(this IQueryable<tsource> source, Expression<Func<TSource, bool>> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    return source.Provider.CreateQuery<tsource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression, Expression.Quote(predicate) }));
}

Unlike the "Where" method of the "Enumerable", this method does not have a delegate to do the filtering. And also the expression can not do the filtering either, it is the IQuerable.Provider which does the filtering. The provider takes the expression tree and does filtering later by converting expression tree to provider specific algorithm like TSQL.


IEumberable<t> is very easy to implement, in fact all the collection they are IEnumberable<T>. Iterator makes it even easier. So there is not such thing as implementing a IEnumberableProvider, because the delegate does the query. But to implement IQueryable is more difficult, because expression does not query. It is IQueryProvider does the job. You need to implement IQuerableProvider


public interface IQueryProvider
{
    IQueryable CreateQuery(Expression expression);
    IQueryable<telement> CreateQuery<telement>(Expression expression);
    object Execute(Expression expression);
    TResult Execute<tresult>(Expression expression);
}

Jul 28, 2009

Raise Event from outside

Normally raising event is the responsibility side of a class, but in workflow there is a need to raise event from outside. Here is the code that allow client dynamically raise event externally.

class EventRaiser
    {
        static BindingFlags getEventFlags = BindingFlags.Instance | BindingFlags.NonPublic;
        private object _eventObject;
        private MethodInfo _eventInvoker;

        public EventRaiser(object hostingObject, string eventName)
        {
            FieldInfo fieldInfo = hostingObject.GetType().GetField(eventName, getEventFlags);
            _eventObject = fieldInfo.GetValue(hostingObject);
            _eventInvoker = _eventObject.GetType().GetMethod("Invoke");
        }

        public void RaiseEvent(WorkflowEventArguementBase argument)
        {
            _eventInvoker.Invoke(_eventObject, new object[] { null, argument });
        }
    }

Jul 19, 2009

Disconnected Update with Entity Framework

In the first demo, we get disconnected entity, make change of it, and get copy of original copy from the database, and apply the changed entity to the original entity by using context.ApplyPropertyChanges method, and save it back to the database.

public void DemoDisconnectedUpdate1()
{
    //using NoTracking to simulate the disconnected enviorment
    //or you can use context.Detach() to simulate that
    context.Contacts.MergeOption = MergeOption.NoTracking;
    var pendingContact = context.Contacts.Where(c => c.ContactID == 709).First();
    //change
    pendingContact.FirstName = "somebody";
    //
    ApplyChange1(pendingContact);
}

public void ApplyChange1(EntityObject pendingEntity)
{
    context = new PEF();
    context.GetObjectByKey(pendingEntity.EntityKey);
    context.ApplyPropertyChanges(pendingEntity.EntityKey.EntitySetName, pendingEntity);
    context.SaveChanges();
}

Unlike the first demo, in the second demo, we use a anonymous typed object to represent the change of the entity, and apply the change directly to the original version directly using reflection.

public void DemoDisconnectUpdate2()
{
    EntityKey key = new EntityKey("PEF.Contacts", "ContactID", 709);
    var changes = new { FirstName = "xyz" };
    UpdateEntity(key, changes);
}

public void UpdateEntity(EntityKey key, object changes)
{
    var original = context.GetObjectByKey(key);
    ApplyChange(changes, original);
    context.SaveChanges();
}

public void ApplyChange(object changes, object original)
{
    Type newType = changes.GetType();
    Type oldType = original.GetType();
    var newProperties =  newType.GetProperties();
    foreach (var newProperty in newProperties)
    {
        var oldProperty = oldType.GetProperty(newProperty.Name);
        if (oldProperty != null)
        {
            oldProperty.SetValue(original, newProperty.GetValue(changes, null), null);
        }
    }
}

Jul 16, 2009

Reference and EntityKey

When add an entity to your objectContext, if the entity reference an other existing entity, but that entity is not in memory, you need to create a EntityKey like the following.

 var address = new Address();
 address.City = "SomeCity";
 address.AddressType = "Home";
 address.ModifiedDate = DateTime.Now;
 address.ContactReference.EntityKey = new EntityKey("PEF.Contacts", "ContactID", 709);
 
 context.AddToAddresses(address);
 context.SaveChanges();

Jul 12, 2009

Naming in Entity Framework

When using the entity framework designer, you create you entity model with a naming convention. For example, a table "Customer" will map to a entity type "Customer" and entity set "CustomerSet" . It is very tempting to change the name of "CustomerSet" to to Customers. But what about Criterion, its plural forms is Criteria, what about Equipment, it is plural forms is also Equipment. I feel that the default naming convention is good enough, because it tells you it is a set and also my configuration is kept to minimum, isn't this the spirit of convention over configuraiton?

How ObjectContext manage entities

Those objects were created by an internal process called object materialization, which takes the returned data and builds the relevant objects for you. Depending on the query, these could be EntityObjects, anonymous types, or DbDataRecords. By default, for any EntityObjects that are materialized, the ObjectContext creates an extra object behind the scenes, called an ObjectStateEntry. It will use these ObjectStateEntry objects to keep track of any changes to their related entities. If you execute an additional query using the same context, more ObjectStateEntry objects will be created for any newly returned entities and the context will manage all of these as well. The context will keep track of its entries as long as it remains in memory. The ObjectContext can track only entities. It cannot keep track of anonymous types or nonentity data that is returned in a DbDataRecord.

ObjectStateEntry takes a snapshot of an entity's values as it is first created, and then stores the original values and the current values as two separate sets. ObjectStateEntry also has an EntityState property whose value reflects the state of the entity (Unchanged, Modified, Added, Deleted). As the user modifies the objects, the ObjectContext updates the current values of the related ObjectStateEntry as well as its EntityState.

The object itself also has an EntityState property. As long as the object is being managed by the context, its EntityState will always match the EntityState of the ObjectStateEntry. If the object is not being managed by the context, its state is Detached.

ObjectContext has a single method, SaveChanges, which persists back to the database all of the changes made to the entities. A call to SaveChanges will check for any ObjectStateEntry objects being managed by that context whose EntityState is not Unchanged, and then will use its details to build separate Insert, Update, and Delete commands to send to the database. ObjectContext can monitor the change of both entity and entity reference.

Pros and Cons of Load and Include

You have some things to consider when choosing between the Load and Include methods. Although the Load method may require additional round trips to the server, the Include method may result in a large amount of data being streamed back to the client application and then processed as the data is materialized into objects. This would be especially problematic if you are doing all of this work to retrieve related data that may never even be used. As is true with many choices in programming, this is a balancing act that you need to work out based on your particular scenario. The documentation also warns that using query paths with Include could result in very complex queries at the data store because of the possible need to use numerous joins. The more complex the model, the more potential there is for trouble.

You could certainly balance the pros and cons by combining the two methods. For example, you can load the customers and orders with Include and then pull in the order details on an as-needed basis with Load. The correct choice will most likely change on a case-by-case basis.

public static void DeferredLoadingEntityReference()
{
    var addresses = from a in context.Addresses select a;
    foreach (var address in addresses)
    {
        if (address.CountryRegion == "UK")
            address.ContactReference.Load();
    }
}


public static void EagerLoadWithInclude()
{
    var test = from c in context.Contacts.Include("Addresses")
               where c.LastName == "Smith"
               select c;
    test.OuputTrace();
}

Debuging ObjectQuery

When you write query with ObjectQuery, it use IQueryable interface. Following extension function help your to debug ObjectQuery more easily.

public static class IQueryableExtenstion
{
    public static ObjectQuery ToObjectQuery(this IQueryable query)
    {
        return query as ObjectQuery;
    }

    public static ObjectQuery<T> ToObjectQuery<T>(this IQueryable<T> query)
    {
        return query as ObjectQuery<T>;
    }


    public static string ToDatabaseSql(this IQueryable query)
    {
        try
        {
            return query.ToObjectQuery().ToTraceString();
        }
        catch
        {
            return null;
        }
    }

    public static string ToEntitySql(this IQueryable query)
    {

        try
        {
            return query.ToObjectQuery().CommandText;
        } 
        catch
        {
            return null;
        }
    }

    public static void OuputTrace(this IQueryable query)
    {
        Console.WriteLine(query.ToDatabaseSql());
        Console.WriteLine(query.ToEntitySql());
    }
   
}

//to use the extension function you can write the following code
 var test = from a in context.Addresses
            let c = new { a.Contact.FirstName, a.Contact.LastName, a.CountryRegion }
            group c by c.CountryRegion into mygroup
            where (mygroup.Count() &gt; 150)
            select mygroup;
 test.OuputTrace();