Li Chen's Blog

  • Delegate performance of Roslyn Sept 2012 CTP is impressive

    I wanted to dynamically compile some delegates using Roslyn. I came across this article by Piotr Sowa. The article shows that the delegate compiled with Roslyn CTP was not very fast. Since the article was written using the Roslyn June 2012, I decided to give Sept 2012 CTP a try.

    There are significant changes in Roslyn Sept 2012 CTP in both C# syntax supported as well as API. I found Anoop Madhisidanan’s article that has an example of the new API. With that, I was able to put together a comparison. In my test, the Roslyn compiled delegate is as fast as C# (VS 2012) compiled delegate. See the source code below and give it a try.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    using Roslyn.Compilers;
    using Roslyn.Scripting.CSharp;
    using Roslyn.Scripting;
    
    namespace RoslynTest
    {
        class Program
        {
            public Func del;
    
            static void Main(string[] args)
            {
                Stopwatch stopWatch = new Stopwatch();
    
                Program p = new Program();
                p.SetupDel(); //Comment out this line and uncomment the next line to compare
                //p.SetupScript();
                stopWatch.Start();
                int result = DoWork(p.del);
                stopWatch.Stop();
                Console.WriteLine(result);
                Console.WriteLine("Time elapsed {0}", stopWatch.ElapsedMilliseconds);
                Console.Read();
            }
    
            private void SetupDel()
            {
                del = (s, i) => ++s;
            }
    
            private void SetupScript()
            {
                //Create the script engine 
                //Script engine constructor parameters go changed 
                var engine=new ScriptEngine(); 
                
                //Let us use engine's Addreference for adding the required 
                //assemblies 
                new[] 
                { 
                    typeof (Console).Assembly, 
                    typeof (Program).Assembly, 
                    typeof (IEnumerable<>).Assembly, 
                    typeof (IQueryable).Assembly 
                }.ToList().ForEach(asm => engine.AddReference(asm)); 
                
                new[] 
                { 
                    "System", 
                    "System.Linq", 
                    "System.Collections", 
                    "System.Collections.Generic" 
                }.ToList().ForEach(ns=>engine.ImportNamespace(ns)); 
                //Now, you need to create a session using engine's CreateSession method, 
                //which can be seeded with a host object 
                var session = engine.CreateSession();
    
                var submission = session.CompileSubmission>("new Func((s, i) => ++s)");
                del = submission.Execute();
                //- See more at: http://www.amazedsaint.com/2012/09/roslyn-september-ctp-2012-overview-api.html#sthash.1VutrWiW.dpuf       
            }
    
            private static int DoWork(Func del)
            {
                int result = Enumerable.Range(1, 1000000).Aggregate(del);
                return result;
            }
        }
    }
    

     

    Since Roslyn Sept 2012 CTP is already over a year old, I cannot wait to see a new version coming out.

  • Gave 3 presentations at SoCal Code Camp (UCSD) today

    I gave 3 presentations at SoCal Code Camp today at University of California, San Diego.

    The first two presentations are co-presented with our summer intern Christopher Chen. Clicks the links below to download the power point.

    Creating an Orchard website on Azure in 60 minutes

    Customizing Orchard Websites without limit

    My source code can be found on github: https://github.com/aspcompiler/sdcodecamp

    Lastly, several people asked whether we can create mailing list to keep in touch. I created a Linkedin group called SoCal Orchard SIG. Welcome to join!

    My last talk was:

    Machine learning made simple

  • Asp.NET ReportViewer “report execution has expired or cannot be found” error when using session state service or SQL Server session state

    We encountered an error like:

    ReportServerException: The report execution x5pl2245iwvvq055khsxzlj5 has expired or cannot be found. (rsExecutionNotFound)]
       Microsoft.Reporting.WebForms.ServerReportSoapProxy.OnSoapException(SoapException e) +72
       Microsoft.Reporting.WebForms.Internal.Soap.ReportingServices2005.Execution.ProxyMethodInvocation.Execute(RSExecutionConnection connection, ProxyMethod`1 initialMethod, ProxyMethod`1 retryMethod) +428
       Microsoft.Reporting.WebForms.Internal.Soap.ReportingServices2005.Execution.RSExecutionConnection.GetExecutionInfo() +133
       Microsoft.Reporting.WebForms.ServerReport.EnsureExecutionSession() +197
       Microsoft.Reporting.WebForms.ServerReport.LoadViewState(Object viewStateObj) +256
       Microsoft.Reporting.WebForms.ServerReport..ctor(SerializationInfo info, StreamingContext context) +355

    [TargetInvocationException: Exception has been thrown by the target of an invocation.]
       System.RuntimeMethodHandle._SerializationInvoke(Object target, SignatureStruct&amp; declaringTypeSig, SerializationInfo info, StreamingContext context) +0
       System.Reflection.RuntimeConstructorInfo.SerializationInvoke(Object target, SerializationInfo info, StreamingContext context) +108
       System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context) +273
       System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder) +49
       System.Runtime.Serialization.ObjectManager.DoFixups() +223
       System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) +188
       System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) +203
       System.Web.Util.AltSerialization.ReadValueFromStream(BinaryReader reader) +788
       System.Web.SessionState.SessionStateItemCollection.ReadValueFromStreamWithAssert() +55
       System.Web.SessionState.SessionStateItemCollection.DeserializeItem(String name, Boolean check) +281
       System.Web.SessionState.SessionStateItemCollection.DeserializeItem(Int32 index) +110
       System.Web.SessionState.SessionStateItemCollection.get_Item(Int32 index) +17
       System.Web.SessionState.HttpSessionStateContainer.get_Item(Int32 index) +13
       System.Web.Util.AspCompatApplicationStep.OnPageStartSessionObjects() +71
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2065

    This error occurs long after the report viewer page has closed. It occurs to any asp.net page in the application, rendering the entire application unusable until the user gets a new session.

    The cause of the problem is that the ReportViewer uses session state. When a page retrieves session from any out-of-state session, the session variable of type Microsoft.Reporting.WebForms.ReportHierarchy is deserialized from the session storage. The deserialization could cause the object to connect to the report server when the report is no longer available.

    The solution is simple but not pretty. We need to clean up the session variable when the report viewer page is closed. One way is to add some Javascript to the page to handle the window.onunload event. In the event handler, call a web service to clean up the session variable. The name of the session variable appears to be randomly generated. So we need to loop through the session variable to find a variable of the type Microsoft.Reporting.WebForms.ReportHierarchy. Microsoft has implemented pinging between the report viewer and the report server to keep the report alive on the server when the report viewer is up; I hope they will go one step further to take care of this problem.

  • Running an intern program

    This year I am running an unpaid internship program for high school students. I work for a small company. We have ideas for a few side projects but never have time to do them. So we experiment by making them intern projects. In return, we give these interns guidance to learn, personal attentions, and opportunities with real-world projects.

    A few years ago, I blogged about the idea of teaching kids to write application with no more than 6 hours of training. This time, I was able to reduce the instruction time to 4 hours and immediately put them into real work projects. When they encounter problems, I combine directions, pointer to various materials on w3school, Udacity, Codecademy and UTube, as well as encouraging them to  search for solutions with search engines. Now entering the third week, I am more than encouraged and feeling accomplished. Our the most senior intern, Christopher Chen, is a recent high school graduate and is heading to UC Berkeley to study computer science after the summer. He previously only had one year of Java experience through the AP computer science course but had no web development experience. Only 12 days into his internship, he has already gain advanced css skills with deeper understanding than more than half of the “senior” developers that I have ever worked with. I put him on a project to migrate an existing website to the Orchard content management system (CMS) with which I am new as well. We were able to teach each other and quickly gain advanced Orchard skills such as creating custom theme and modules. I felt very much a relationship similar to the those between professors and graduate students. On the other hand, I quite expect that I will lose him the next summer to companies like Google, Facebook or Microsoft.

    As a side note, Christopher and I will do a two part Orchard presentations together at the next SoCal code camp at UC San Diego July 27-28. The first part, “creating an Orchard website on Azure in 60 minutes”, is an introductory lecture and we will discuss how to create a website using Orchard without writing code. The 2nd part, “customizing Orchard websites without limit”, is an advanced lecture and we will discuss custom theme and module development with WebMatrix and Visual Studio.

  • Fun with Orchard, Webmatrix, Git and Azure

    Why Orchard?

    Our company wants to convert an old html site to a content management system. We considered between Wordpress and Orchard and picked Orchard. This post strongly influenced us. It is ASP.NET MVC vs php. We are a .net shop. We thought it would be easier to do custom development with Orchard.

    Why Webmatrix?

    There are a few reason we used Webmatrix:

    1. Webmatrix works with Orchard very well. Many Orchard training materials use Webmatrix.
    2. Webmatrix is free. We have interns here working on Orchard. We do not have to consume a Visual Studio license.
    3. Webmatrix has an excellent story working with both Git and Azure.

    Why Git?

    We would like to have a version control system. Git is a free and open source distributed version control system. There are several free Git hosts, such as GitHub, Codeplex, and BitBucket. So we picked Git.

    Why Azure?

    We would like to have website that our entire team can see. Azure web site is an excellent option for us. It is very easy to host Orchard with an Azure website, either with Sql Compact Edition or with Azure SQL Database. Azure also integrates with Git very well.

    So how do they work together?

    Although it is possible to edit a Azure hosted web site directly with Webmatrix, we hosted out source code in Git because we need a source control system.

    It is very easy to work with Git from Webmatrix. One can use git with an existing site or open a site directly from git.

    The Sql Server migration solution in Webmatrix is amongst the easiest way to migrate a Sql CE database to Azure SQL Database.

    It is also fairly easy to setup an Azure website to pull source code from git directly and build the source code. Each time when we push a changeset to git, Azure is notified and it will automatically pull and build the website. For Orchard, the “built” is actually not more than an xcopy. We just need to embed a .deployment file in our source code. See David Haden’s post for more details.

  • The history.back and refresh problem

    It is fairly common in applications that we have a list page/details page pairs. When we need to add a new record or edit an existing record, we click on the “Add New” link or the “Edit” link from the list page to go to the details page. When we finish adding or editing, we go back to the list page and expect to see the information updated.

    At the first glance, developer can use history.back if no post-back occurred or use response.redirect if a post-back occurred. However, what if the list page has a filter or is at a page number other than the first? How do we return to where we were on the list page?

    If we search Bing on “history.back and refresh”, we can see a number of discussions. However, there are no good solutions. It is difficult to have a Javascript only solution because Javascript has the life time of a page. So we need a bit of assistance from the server but we do not want to leave session variables behind because we would leave many session variables behind if the application has many list/detail pairs. The following is one possible solution to the problem:

    1. Change links to the detail page on the list page to post-backs . For ASP.NET Web Form, this can be easily done by changing links to LinkButtons.
    2. Upon posting back to the list page, capture the current filter criteria and page number. Save the information to a session variable and do a response.redirect to the details page.
    3. From the details page, save the filter data from the list page into a hidden control or use ViewState if using ASP.NET Web Form. Remove the session variable.
    4. Use post-back in the details page for both “Save” and “Cancel”. Save the filter data into the session again and do a response.redirect to the list page.
    5. From the list page, check the existence of a session variable for filter. If it exists, populate the filter and page number and remove it from the session. We have thus returned to where we were on the list page and have left no trace of session variables behind.
  • Controlling the display of ASP.NET validator controls

    Recently, I worked on an old webform project and used the asp.net validation controls. I previously used some features of validation controls, but I encountered more scenarios this time. I found these controls are fairly flexible and can be configured to work in many different ways:

    Validator Controls

    The most important properties that control the display are Text, ErrorMessage and Display properties.

    What is the difference between the Text and ErrorMessage properties. According to MSDN:

    If the Text property is set, that text will override the text specified in the ErrorMessage property and appear in the validation control. However, the text specified by the ErrorMessage property always appears in the ValidationSummary control.

    One scenario is that you might set Text to “*” and ErrorMessage to the description of the error. You will see an “*” next to the control to validate and a details message in the validation summary section.

    The display property takes 3 values:

    Display Behavior Description
    None
    The validation message is never displayed inline.
    Static Space for the validation message is allocated in the page layout.
    Dynamic Space for the validation message is dynamically added to the page if validation fails.

    To show error only in the validation summary section, set the Display property of the validator controls to None.

    Validation Summary Controls

    The most important properties that control the display are HeaderText, DisplayMode, ShowSummary and ShowMessageBox properties.

    If we turn Show Summary off and ShowMessageBox on, the summary will be displayed as a message box. Note that it is necessary to leave EnableClientScript to true to use ShowMessageBox.

    Supposing we only want to display a “*” next to each control and a generic message portion, we only need to test Text of each validator control to “*”, ErrorMessage to blank and set the generic message to the HeaderText of the ValidationSummary control.

    The ASP.NET validator controls have a good combination of properties to work out all the scenario that I encountered in the project.

  • modern.ie

    We are planning to update our very old web application so that it works better with modern web browsers. I have heard of modern.ie in the past and decided to give it a try. The site has a scanner that can scan a URL entered by a user. Unfortunately, our site requires log-in before getting to the page we want to scan. Fortunately, the site also offers a downloadable scanner that we can use in our local development environment.

    I downloaded the scanner. It is packaged as a zip file. I unzipped the package and open the readme file. The tools requires node.js to work. Fortunately, it is fairly easy to setup the tool following the instructions. Firstly, download and install node.js; accept all defaults. The setup will add Node.js to the path. Although Node.js is known for hosting asynchronous web applications, it is actually just a javascript executing environment. Next, I open the command prompt, change to the directory that I unzipped the modern.ie tool and run “node lib/service.js”. A node hosted web server is listening on port 1337 so we just need to open a web browser and points to http://localhost:1337/. We can then enter the URL of a web page to scan. The scanner submits the data to modern.ie and a report is generated. The report is very good and it offers many suggestions and links that helps us to improve the page.

  • Is it time for cloud-based ASP.NET IDE?

    We already have a standard IDE in Visual Studio. We also have a very innovative IDE in WebMatrix that can work with node.js and php in addition to ASP.NET. Why do we need another IDE? Well, let me first talk about the feasibility and then throw in some ideas on what we could do with it.

    I have noticed CodeMirror for a long time. Recently, I have also noticed ACE on which the Cloud9 IDE is based. I was impressed that both CodeMirror and ACE supported Typescript soon after it was released. I was also impressed with the Cloud9 IDE that can debug Node.js code. All these projects have benefited from rapid improvement of the Javascript engine in modern browsers and I think that the era for very functional web-based IDEs has arrived.

    So what can we do with a cloud-based IDE? Firstly, like what Cloud9 demonstrated, the code lives on the cloud. Secondly, people can collaborate. Thirdly, I think it is possible to improve experience to what we have never seen before, so let me elaborate below.

    In Visual Studio, when we want to see how the ASP.NET page looks like, we switch to the designer mode but that is not really close to what we see at runtime. In a cloud-based IDE, we can see the code and how it renders side-by-side, like what JsFiddle has demonstrated. ASP.NET does not execute the code on the website directly; it first compiles the code into the “Temporary ASP.NET Files” directory and executes the assemblies from there. That makes it feasible to edit and run the code at the same time.

    Visual Studio has been heavy on ORM (i.e., entity framework) and lighter on code-generation. I have been favoring code-generation over ORM. This is because with ORM we are tweaking a black box to generate desired SQL. With code-generation, we can see exactly what we get and tweak the templates when necessary. Visual Studio has limited runtime information; it gets its information either from parsing the code, or from meta-data stored in XML files. With a cloud-based IDE that is working with running code, it is possible to get richer runtime information and generate code (or scaffold) under much wider scenarios. So how do we map the server-side code to html in the browser? That is where ideas like source map could help, and we have very good tools in querying DOM already.

    So I believe all the technical pieces for a cloud-based ASP.NET IDE are available.