Thursday, October 28, 2010

Rendering asp.net controls with dynamic ids

You have a legacy asp application with lots of html and server side code.

And you you have a loop in which you are trying to add server controls and you want their ids to be dynamically generated.

You want the mark up to look like the following.  Here for this blog post purposes I am using textbox.


<input name="0" type="text" id="0" />
 <br />
<
input name="1" type="text" id="1" />
 <br />
<
input name="2" type="text" id="2" />
 <br />
<
input name="3" type="text" id="3" />
 <br />
<
input name="4" type="text" id="4" />



You might intuitively try the following

<%  for (var i = 0 ; i <5; i++){ %>
 <asp:TextBox runat="server" id="<%# i %>" />
<% }
%>




But this results in to the following error

The ID property of a control can only be set using the ID attribute in the tag and a simple value. Example: <asp:Button runat="server" id="Button1" />

Workaround for this issue is as follows.

First the Markup.

<% for (var i = 0; i < 5; i++) {

AddTextBox(i);

} %>

Here we are adding 5 text boxes dynamically to the page in place.

This kind of code gets executed at the rendering stage of the page life cycle.  Trick is get the html out of the text box and just render in place.

And code for AddTextBox method


void AddTextBox(int i){


    var ctrl = new TextBox() { ID = i.ToString() };


    var sb = new StringBuilder();


    using (var sw = new StringWriter(sb)){


        using (var textWriter = new HtmlTextWriter(sw)){


            ctrl.RenderControl(textWriter);


        }


    }


    Response.Write(sb.ToString());


}





Here we are creating a new TextBox control and setting its id property dynamically.   And then using RenderControl method, we are populating the StringBuilder instance.  And then outputting the value to response stream.

This can easily be turned in to an extension method.  Then the usage looks like the following

<%= TextBox.ToHtml(id, val) %>

Monday, September 6, 2010

Windows Live Writer and WordPress problem solved

While I was trying to set up windows live writer to post to this site, I got the following error.
Invalid Server Response - The response to the blogger.getUsersBlogs method received from the weblog server was invalid
Googling didn't help to find a solution to this problem.  I fired up fiddler to see what is going on with the response.  Fiddler showed the following as the first line in the response.
b>Warning</b>:  include(./wp-load.php) [<a href='function.include'>function.include</a>]: failed to open stream: No such file or directory in ........
The above line is coming from xmlrpc.php.
ah..ha.. This blog was set up as a root folder.  Somehow WordPress assumes that all blogs must be in a sub-folder of the root site.

Changing that include line from
include('./wp-load.php');
to
include('wp-load.php');
solved the issue. 
And this blog post is from Windows Live Writer!
:)

Sunday, September 5, 2010

ubuntu - rails TCPServer Error: Address already in use

When you try to start the rails server with the following command
rails s

and if webrick doesn't start and throws "Address already in use" error, following are the directions on ubuntu to kill all ready running

Type the following from terminal

lsof|grep 3000


This gives a list of running processses that are using 3000 port.  Find a line that starts with ruby, and note the process id

ruby  12345 ....


Type the following command at terminal

kill -9 12345


And your webrick server should start fine now

Rails for windows developer

I have been working in the Microsoft world for too many years.  Every time I attempt to venture in to learning ruby on rails, I end up setting up every thing from scratch and spend tons of time to get started.  And leave all of that to only start again after few months.  It feels like I am doing this over and over again.  Finally I decided to write down the instructions needed to set up Rails development environment on Ubuntu virtual machine.

  • Do not use windows environment to develop on Rails.  You cannot stand the friction after a while.  Not much support in the community if you are struck.

  • I found it best to use Ubuntu on a virtual machine. I tried to use  Wubi, which is a fantastic tool. But duel booting means rails environment is not a click away.  And a number one reason for not spending much time on rails learning.

  • If you are taking rails seriously you mush be comfortable with either mac or unix environments.

  • I decided to use ubuntu as I would like to have rails on my windows machine via vmware workstation.  VirtualBox will do fine.

  • I tried multiple IDEs and finally settled on RubyMine.  This choice is a no-brainer as I am used to Resharper on visual studio.
Setup instructions

  • Install vmware workstation

  • Insall ubuntu on vmware.  Grab the iso files from ubuntu.  I used 10.1 beta.   15GB space and 1GB RAM

  • Create a shortcut for Terminal on the panel.  You will be using this a lot.

Installing ruby, rvm and rails
Open the terminal and type the following at the prompt
sudo apt-get install curl git-core ruby
Install rvm by typing the following
bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
At the end of the installation, change the .bashrc file.  Type the following at the command prompt

gedit .bashrc

Replace the following text in .bashrc file
[ -z "$PS1" ] && return
with
if [[ -n "$PS1" ]]; then

And add the following to the end of the file

if [[ -s $HOME/.rvm/scripts/rvm ]] ; then source $HOME/.rvm/scripts/rvm ; fi

fi

Verify the installation of rvm by typing

rvm -v

Close the terminal and reopen it

Install ruby 1.92 packages by typing the following at prompt


sudo aptitude install build-essential bison openssl libreadline5 libreadline-dev curl git-core zlib1g zlib1g-dev
libssl-dev vim libsqlite3-0 libsqlite3-dev sqlite3 libreadline-dev libxml2-dev git-core subversion autoconf

Use rvm to install ruby 1.9.2 by typing the following command


rvm install 1.9.2-head

Set default ruby version in rvm

rvm --default 1.9.2-head
Type the following at the prompt

ruby -v

You should see the following

ruby 1.9.2p0 .....

Now ruby set up is done.  Type the following at the prompt to install Rails


gem install rails

That is it!  Rails is now installed on your ubuntu setup

Installing RubyMine IDE
I used 2.5 EAP version of RubyMine

Grab RubyMine-<version>.tar.gz file.  And extract that to a known folder using default ubuntu archiver

Move the unpacked rubymine to /opt/rubymine by typing the following command at prompt


sudo mv RubyMine-96.1085 /opt/rubymine

Create an app launcher on the panel bar.  Right click on the panel and choose add to panel and create custom application launcher

Set the command option to opt/rubymine/bin/rubymine.sh

Choose the icon from opt/rubymine/bin/rubymine.png

Installing Sun Java
RubyMine needs sun java, which is not installed on ubuntu.

Open System --> Administration --> Software sources --> Other Software

Check all the check boxes pointing to http://archive.canonical.com/ubuntu maverick

Open Applications -> Ubuntu Software Center and search for sun java

Install sun-java6-bin, sun-java6-jre, sun-java6-fonts,  , sun-java6-jdk, sun-java6-plugin

Type which java at command prompt.  It should show /user/bin/java

Rubymine needs a symbolic link for java in bin folder.  Type the following command at the prompt

sudo ln -s /usr/bin/java /bin/java

Now you should be able to start RubyMine

Tuesday, August 31, 2010

Asp.Net MVC Multi Area Projects and Intellisense

If your MVC project is divided in to multiple area projects and if you are using portable areas feature of MVCContrib, and if the view pages are stronly typed, intellisense on the view pages might not work.

Only way I was able to make this work is

a. Copy the main web.config file in to the area project

b. Copy the Views\Web.Config in to the areas project under views folder

c. Do not select 'Copy Local' option on System.Web.MVC dll.

Using TestDriven.Net and NCover to boost your team to write more tests

Having a large number of unit tests and sizable number of integrations tests is essential for maintaining a software project or product.  Apart from the quality of those tests, the quantity is some indication that the teams are in the right direction.

I see the following clear benefits of tests among many.

  • If your working code is the truth, tests are the validators of that truth.  Tests are the code's knowledge base.

  • They take out the fear of unknown.  This encourage the developers to refactor the code and improve it instead of merely maitaining it.

  • Tests essentially improve the design of the code

  • Tests helps new developers to come up to speed with the code base quickly


TestDriven.Net is a visual studio plugin that makes it super easy to run the tests right from the IDE.  This plugin integrates well with NUnit GUI and also NCover.

NCover is a code coverage tool.  It shows how much of your source code is covered by the tests.  Once you run the tests using NCover, it produces a report of which parts of the source code is not covered by the tests in percentages.

I found that these numbers play an important role in the developer psyche.  Once developers looks at these numbers, and know that how much of their code is not being tested at all, they can't resist from writing more tests.  I have seen this happening all the time. If stackoverflow.com's success is any proof that developers like numbers, scores, this makes complete sense.

Declare a target coverage percentage to the team and announce which parts of the code reached the target in the daily team meetings.  Like every other thing in development large number of poorly written tests could become a maintenance headache.  Once your team gets in to the track of writing tests, it is very important to review the tests.

Happy testing!

Monday, August 30, 2010

MVC Portable Areas and WebForms

MvcContrib project has a neat little feature called portable areas.  This allows us to develop features as independent units of work in asp.net mvc.

Eric Hester wrote a detailed post on how to use areas in an MVC project.  Jeffery Palermo wrote on how to use portable areas in a webforms project.

Portable areas projects stores all the views in the assembly as enbedded resources.  Normally asp.net runtime look for the page in the file system.  We can change this behavior by making the following call in the application start event of the global.asax file.

HostingEnvironment.RegisterVirtualPathProvider (YourVirtualPathProvider);


Portable areas feature in MVCContrib simply does that.  MvcContrib profject supplies a VirtualPathProvider called AssemblyResourceProvider.

However the above call will fail quietly if your website is precompiled.   This behavior is documented in an MSDN article.  So in order to use the portable areas in your webforms project, you should not use precompile option in the website project.

Sunday, August 29, 2010

Migrating large asp sites to asp.net - website project

In web forms world of asp.net , visual studio offers two options. WebSite projects and WebApplication projects.   If you are starting a green field project and choose to take web forms route,  website projects are definitely not a good option, especially if the site size is large.   But if the site is being migrated from legacy asp site, it is better to stick with website project.  You are not going to benefit a lot from web  application project, if the individual asp.net pages (not in code behind) are going to contain most of the code.

Following are some of my observations from such an effort.

  • Patching gets simpler.   The quickest way to patch an asp page is just copying modified page on to server.   As legacy site is mostly likely contains code a markup combined, this option helps to maintain the new site until these concerns are separated.
  • Site can be precompiled to check for the asp.net page errors.  In web application option, if the code is in asp.net page,  vs.net is not going to compile asp.net pages.   So there is no way to know if there is a problem with a page until runtime.
  • Visual Studio crashes every time if you try to convert a large site in to a web application project.  Your web deployment projects won't finish without crashing.  This instability suggests that you should better stick to website project.
  • Every time you touch the bin folder or web.config or user controls, app domain gets recycled.  This kicks users out.  You should be able to mitigate this a little by choosing some kind of persistent session option.
  • If you choose to deploy precompiled site, with every patch you will be deploying more dlls than necessary.  This is because every refereced dll is going to produce a new version of the dll that is different from the already deployed version.
  • Visual studio suffers from huge performance issues, especially when the site is large.  Combined with Resharper, it feels like being in a hell to use the IDE to make small changes.  If you have automated integration tests, then better not to use Visual Studio for simple changes.
  • You want to turn the 'Build Website' option off, else you will waiting for the compiler to come back for the most part of the work, when ever you modify a sub project item that compiles in to your site's bin.  It is better to defer the build site option to the build server.
  • Your builds are going to be slow.   Every time if some one checks in the code you need to Clean, Build, PreCompile the while site.  Precompile task runs really slow as it has to compile each page in to its own dll and copy every thing in to new directory.  You can speed this a little with in-place precompilation.
  • Deploying involves two steps.
Step 1:    Clean, Build, PreCompile -> to make sure that build is still ok

Step 2:     Clean, Build, Copy web files, copy bin files, copy environment specific config files,  -> if you are not deploying the precompiled site

Copy the precompile outputs, copy environment specific files -> if you are deploying precompiled site

  • You might not be able to use the built-in web server for testing the application, again due the size of the site.