Sunday, October 20, 2013

Disabling Smart Scopes in Ubuntu 13.10

To disable smart scopes in Ubuntu 13.10, go to Settings, Security and Privacy, Search, and flip the switch for the setting Include online search results.

To disable specific scopes, go to the Applications scope (Windows/Super key + A), go to the Dash Plugins section and click on See more results. Click on the scope you want to disable and click the Disable button.

For more tweaks that you can do to your Ubuntu 13.10 setup, take a look at:

Windows RT 8.1 Withdrawn From Store

The Windows RT 8.1 update has been withdrawn from the Microsoft Store because of reports of users being unable to boot their devices after the update. The error code reported on attempting to boot up on affected devices is 0xc000000d. The Windows 8.1 update, however, continues to remain available to users.

Thursday, October 17, 2013

Windows: Network Interface Information

You can easily look up the metric that Windows assigns to your network interfaces by typing the following on a command line:
netsh int ipv4 show interfaces
Windows displays an index, metric, maximum transmission unit, state, and interface name.

While ipconfig is a common way to determine the IP address(es) of you computer, another way to get the IP address is to run:
netsh int ipv4 show ipaddresses

Figuring out which name server you are using is simple too, with the following command:
netsh int ipv4 show dnsservers

For information about IPv6 instead of IPv4, simply replace the '4' with a '6' in the above commands.

ICQ: Where's Its Target Audience?

When you hear about ICQ, you begin to think back to 1998 when you used the Internet messenger to talk to strangers, colleagues, co-workers, classmates, friends, and family. It was also a great way to send mobile text messages (SMS).

Today, ICQ is still supported in every major multi-IM client such as Adium, Pidgin, and Trillian. ICQ also has its own Windows 8 client, apart from clients for iOS, Android, Blackberry, Symbian, Bada, and MacOS. That makes you wonder - who uses ICQ?

ICQ started off as a product by the Israeli firm Mirabilis. It was then sold to America Online, which in turn sold it to a Russian firm, Digital Sky Technologies. It would be highly unlikely that you would meet someone in the US or UK, or even Dubai or India, who uses ICQ. However, ICQ has a lot of users from Russia and Eastern Europe. GoogleTalk, Skype, WhatsApp, and FaceBook Chat may be the current favorites for IM and chat, but ICQ is far from being a has-been in some parts of the world.

Tuesday, October 15, 2013

2 Days To 'Saucy Salamander' Release

With 2 days left to the Ubuntu 13.10 release, which is named Saucy Salamander, a lot of Ubuntu users wonder if it is worth the hassle to upgrade. The new Ubuntu 13.10 comes with smart scopes to provide better searches across the disk, Wikipedia, Amazon, FaceBook, Google Drive and anything else that you have a scope setup for. Ubuntu 13.10 will also feature Click format packages, which have the benefit of including all required dependencies, unlike deb packages.

Fixing Windows 8 WiFi Off Issue

When using Windows 8, the WiFi can turn itself off when switching back and forth from Airplane mode. Disabling Airplane mode does not turn the WiFi back on. When such a problem occurs, press the Windows key and I at the same time (Win+I) to go to the settings, click on Change PC Settings, and go to the Wireless tab. This settings page provides an interface to turn on WiFi adapters.

The following screenshots will guide you through the process:

Step 1: Win+I or Settings from the right side swipe menu

Step 2: Click on Change PC Settings

Step 3: Click on the Wireless settings page

Step 4: Turn On the wireless interfaces

Monday, October 14, 2013

Ubuntu 13.04 Remixes: The Feeling of 'Old' With 13.10 Around The Corner

The release of WattOS last week didn't really get much attention, with the distribution based on Ubuntu 13.04. It may be a stable operating system but with Ubuntu 13.10 just around the corner, having to work with something that is based on Ubuntu 13.04 just gives a feeling of working with old, legacy technology, something that many information technology professionals would like to avoid.

Having said that, there are programmers who still have to deal with Visual Basic 6 source code because of maintenance contracts that were formed by the firms that they work for so there is little that they can do to get away from the drudgery. There still are programmers out there whose primary skill is COBOL programming and every day they get to their offices, they hook up to a mainframe and get started with work.

There are some folk in the I.T. world who still have not given up on old technologies because they didn't want to make the shift. Windows 7 users, Gnome 2 users, and Python 2 programmers are only some of the information technology professionals who decided that they didn't want to adopt an entirely different approach to the way they have been doing things.

Wednesday, October 2, 2013

SQL Server 2012 Express Installation and Troubleshooting

If you have Windows 7 or Windows 8, you can install either the SQL Server 2012 Express or the SQL Server 2012 Developer Edition. The Express edition is typically all you would need, unless you plan to use reporting services and the integration service in which case SQL Server 2012 Developer edition is what you require.

The SQL Server 2012 installation performs the following checks before starting:

  • Can the updates be obtained using the Windows Update service
  • Is the Internet accessible for installing the .NET 4.0 framework
If you have the Windows Update service disabled or something else prevents the search for updates, you would get the error message:

SQL Server Setup could not search for updates through the Windows Update service. You can either check again or click Next to continue. To troubleshoot issues with your Windows Update service, view the link below, ensure you have Internet or network access, and ensure your Windows Update service can find updates interactively through the Windows Update control panel.

I have the Windows Update service disabled, so I additionally got the following:

Error 0x80070422: The service cannot be started, either because it is disabled or because it has no enabled devices associated with it. (Exception from HRESULT: 0x80070422)

You can skip this check because the updates are not mandatory. However, if you do not have the .NET 4.0 framework (or the .NET 4.5 framework) installed, you have to either provide Internet access or install the .NET 4.0 or .NET 4.5 framework before installing SQL Server. If the computer you are installing SQL Server on does not have access to the Internet, you can use the Standalone (offline) installer for the .NET 4.0 or .NET 4.5 framework.

If you choose to use the Internet to install .NET 4.0 through the SQL Server 2012 setup, ensure that the installer is able to complete the installation of the .NET 4.0 framework - that's when it would display the "Install_DotNetCore_Cpu32_Action". If the progress hangs, most likely something is preventing the download (a torrent download, slow Internet connection, or just about anything else).

At times, the installation hangs at one of these actions:
  • Install_vsshell_Cpu32_Action / Install_vsshell_Cpu64_Action
  • Install_sql_ssms_Cpu32_Action / Install_sql_ssms_Cpu64_Action
  • Install_sql_fulltext_Cpu32_Action / Install_sql_fulltext_Cpu64_Action
  • SqlEngineDBStartconfigAction_install_configrc_Cpu32 / SqlEngineDBStartconfigAction_install_configrc_Cpu64
To deal with the issue, start the installation with the minimum options selected and add-on the other features later. If you are installing SQL Server 2012 Express edition, there is little to uncheck during the installation - all you can do is leave out replication. Often, the Full-Text search and SQL Server Management Studio cause hangs, so you can install the core database, restart the computer, and then add on those components later. Running the installation on an under-powered computer can also lead to the hang (when the hang occurs, there's no CPU load, disk activity, or network activity); an alternative is to run the installation on a virtual machine on another computer, and then move the virtual machine to the computer that you want to run it on. If all else fails, try to use a different installation disc or download the setup files again, reboot the computer if Windows Updates or any other setup has executed, and try again.

Python: Why The global Statement

Often, you come across Python developers debugging a piece of code involving global variables. Sure, global variables are the devil, but when you inherit code for a previous developer, you are just going to have to live with it until there's a budget for refactoring or rewriting it. Typically, if you are referencing a global variable within a function, you would 'import' the global variable into the function scope using the global keyword like this:
film_name = "painted skin"
def film():
  global film_name
Now, even when you leave out the global statement, Python is smart enough to figure out that the variable is a global variable, as in this case:
film_name = "painted skin"
def film():
Suppose you perform a variable assignment within this second case, you would have code like this:
film_name = "painted skin"
def film():
  film_name="final fantasy"
When you execute it, all would seem fine and dandy till you decide that you want assignment statement to occur after the print statement like this:
film_name = "painted skin"
def film():
  film_name="final fantasy"
The error that you would now receive reads the following:
UnboundLocalError: local variable 'film_name' referenced before assignment
What has happened in this case and the previous is that when a variable assignment occurs, Python creates a local variable instead of using the global variable. In the case where we only printed the variable value, the global variable was referenced. This can be resolved using the global statement, as indicated in the first case.

Tuesday, October 1, 2013

Python 2 and Python 3: Two 'different' platforms

When you decide to do any Python development today, the first choice that you come across is the version of Python that you want to use. There's Python 2, the programming platform with lots of libraries that do everything except defying gravity, and then there's Python 3. Python 3 is really good as a language, but we have yet to see the programming libraries and support from the larger community. There are tools to assist in porting Python 2 code to Python 3, and vice-versa but there just has not been enough interest generated within the community to create the everything-but-the-kitchen-sink feeling among Python 3 users so the 'early adopters' (c'mon, it's been a few years since Python 3 was introduced, it isn't early any more!) don't really get all of the niceties that Python 2 users get.

The one area where you would notice a shortfall of Python 3 is in GUI application development. Most GUI libraries/frameworks are in a beta or beta-like stage and using them is like having a swinging pendulum-blade right over you. For web development, there are frameworks supporting Python 3 so if your framework of choice does not support Python 3 yet, you can simply switch over to another framework that does.

If you are a newbie who wants to learn Python, there are a couple of built-in Python modules that have been renamed so you can't follow all the examples that you see online if all you have is a Python 3 environment (or vice-versa, in which case you have a Python 3 example but all you have is Python 2 installed). I have been tinkering with Python every now and then, and when I decided to actually take the plunge and adopt Python 3 for automating some of the application configuration that I occasionally have to do, I started off with Python 3. Initially, figuring out the differences in the names of the modules took a while. Now, I don't even look back at Python 2 and hope everyone else becomes a part of the shift from Python 2 to Python 3.

Sunday, September 29, 2013

Enabling AutoComplete In ADT

I got the Android Development Toolkit, which includes Eclipse and the SDK for developing Android applications. After having a go at it for a couple of minutes, I noticed that I didn't have any autocomplete. Being a newbie at Android development (no experience with Android development, apart from a few days of Android coding in 2010 or 2011), I really needed the autocomplete to work so I looked for something that could point me the right way. I finally stumbled upon the settings at:
Window > Preferences > Java > Editor > Content Assist > Advanced

I enabled the Java Proposals, Java Type Proposals, and Java Non-Type Proposals, and as soon as I dismissed the dialog box by clicking the Ok button, I was able to use Ctrl+Space for the code autocompletion!

Saturday, September 28, 2013

Python: Subclassing the BaseHTTPRequestHandler

As discussed in my previous post, Python provides the HTTPServer class for listening to HTTP requests and dispatching them to request handlers. To write our own handler, we can create a subclass of BaseHTTPRequestHandler and handle the requests by providing functions named with the 'do_' prefix followed by the HTTP action verb (Eg. do_GET, do_HEAD, do_POST etc). The following is an example that uses this approach to create a web server.

from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
from http.server import SimpleHTTPRequestHandler

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
 server_address = ('', 8000)
 httpd = server_class(server_address, handler_class)

class MyHandlerForHTTP(BaseHTTPRequestHandler):
 def do_GET(self):
  self.send_header('Content-Type', 'text/plain')
  self.wfile.write(bytes('Hello World\n', 'UTF-8'))
  self.wfile.write(bytes('You have requested '+self.path+'\n', 'UTF-8'))


In this example, we created a class named MyHandlerForHTTP that inherits from BaseHTTPRequestHandler and defined the do_GET method within it. The BaseHTTPRequestHandler class provides methods to set the HTTP response status code, output the headers, and write data to the response stream. Note that you do not have to call the close method on the wfile member as the BaseHTTPRequestHandler class implicitly calls the flush method of the wfile member after the execution of the do_* method.

Python HTTP Web Server

Python makes it extremely simple to create a web server. I adapted the run function provided in the Python documentation to create the following example.

from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
from http.server import SimpleHTTPRequestHandler

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
 server_address = ('', 8000)
 httpd = server_class(server_address, handler_class)


In the code above, we first import the HTTPServer, BaseHTTPRequestHandler, and SimpleHTTPRequestHandler classes from the http.server module (if you want to know more about modules, look at my slides on Python Modules). We then have a run function that accepts the name of an HTTP server class and an HTTP request handler class as parameters.

The HTTPServer class is used to listen for web requests and dispatch them to request handlers. Request handlers are what we use to figure out what needs to be done and to send a response. The BaseHTTPRequestHandler calls methods with a 'do_' prefix followed by the name of the HTTP action verb (more on that in another post). In the example above, we use a SimpleHTTPRequestHandler that provides the functionality out-of-the-box to serve files from the current directory.

Our example above acts as a glue between the HTTP server and the SimpleHTTPRequestHandler class without doing the actual processing on its own. In another blog post, I will describe how you can create your own request handler class to process requests in Python code.

[Python] TypeError: str does not support buffer interface

When writing data, such as to sockets, you probably see a lot of code that calls a write function and passes in a string like this:
self.wfile.write('Hello World')

This code ran perfectly well in Python 2.x, but not so in Python 3.x. In Python 2.x, strings that contained only ASCII characters could be passed as data but if the strings contained characters that couldn't be represented as ASCII characters, a UnicodeDecodeError would occur.

Python 3.x treats text and binary data as distinct types, and raises a TypeError if you provided text where binary data was expected. In Python 3.x, you have to convert text data to binary data using the bytes function, so expect to rewrite your code to look like the following:
self.wfile.write(bytes('Hello World', 'UTF-8'))

Wednesday, September 25, 2013

SQL Monitoring / Query Analysis with MySQL

I'll keep this post a short one. I wanted to view the queries that are being run against a MySQL database and found the simplest way to do it is to view the queries in the general log file using tail. There are 2 variables: general_log to set the logging ON or OFF, and the general_log_file, which indicates the location of the log file.

The following is dump of my MySQL client output:

mysql> SHOW VARIABLES LIKE "general_log%";
| Variable_name    | Value                            |
| general_log      | OFF                              |
| general_log_file | \xampp\mysql\data\reddythink.log |
2 rows in set (0.00 sec)

mysql> SET GLOBAL general_log = 'ON';
Query OK, 0 rows affected (0.08 sec)

mysql> SET GLOBAL general_log = 'OFF';
Query OK, 0 rows affected (0.04 sec)

Friday, September 20, 2013

Oracle DECODE and CASE expressions

The use of the DECODE function in Oracle is to substitute a value or expression with another. The CASE expressions serve a similar purpose but can be used in a wider variety of scenarios.

Let's say you have a character field in the database and you want to select data from the table and display a more user-friendly value instead of a single character. You can use the DECODE function to specify the column or expression to be checked followed by a pair of values or expressions to be matched with a substitution value, and finally a substitution value to be used if none of the matching values or expressions matched. Here is an example:

A table r5translines containing a column trl_type has the value 'I' for goods issued (sent out), 'RETN' for goods returned (such as when a defective product is returned), and 'RECV' for goods received (such as goods received from a supplier). To display this information in a user-friendly form, the SELECT statement can be writted with a DECODE statement as follows:
SELECT DECODE(trl_type, 'I', 'Issue', 'RETN', 'Return', 'RECD', 'Received', 'Unknown') FROM r5translines;

You can also do this using a CASE expression as follows:
SELECT CASE trl_type WHEN 'I' THEN 'Issue' WHEN 'RETN' THEN 'Return' WHEN 'RECD' THEN 'Received' ELSE 'Unknown' END CASE FROM r5translines;

In another selection of data, let's say you want to display the string 'Incoming' for received or returned goods, and the string 'Outgoing' for goods issued. You can use a CASE expression in a slightly different manner as follows:
SELECT CASE WHEN trl_type IN ('RECD', 'RETN') THEN 'Incoming' ELSE 'Outgoing' END CASE FROM r5translines;

Wednesday, September 18, 2013

Missing tools.jar during deployment

This is just a quick note to suggest a possible solution to the missing tools.jar file when deploying configuration changes in Infor EAM - if you get an error message from the deployment script indicating that the tools.jar file is missing, install a JDK (not a JRE) and set the JAVA_HOME environment variable to point to the path of the JDK directory. Alternatively, you can copy the tools.jar file from a JDK into the java/lib directory in the Infor EAM directory.

Tuesday, September 17, 2013

Infor EAM 10.1.2 Installation

The Infor EAM software and CD keys are available to channel partners, in addition to access to Infor Xtreme, the system for obtaining tech support and looking up the knowledge base. The installer consists of 3 CDs:
(i) Database objects setup (there's a CD for SQL Server and another for Oracle)
(ii) Application setup
(iii) Advanced Reports setup

The installation logs do not help much during the installation process for the database objects setup other than for verifying that the installation occurred as intended. If the directory locations provided to the Infor EAM database objects setup do not exist, the setup application goes all the way to the end without performing an installation. Ensure the installation paths exist, and set the path for the data files, log files, and index files to the data directory where you would normally store them for your database installation.

The application setup is just as tricky as the database objects setup - the installer doesn't tell you if you are missing the Visual C++ 10.0 run time DLL so make sure you install it before starting the application setup. You can tell if you are missing the Visual C++ 10.0 run time DLL if the Infor Application HTTP service is missing (you should see 2 services for Infor in services.msc). After the installation completes and the web server does display a login screen, you can check the WildFly/JBoss logs for additional error messages. You may have a warning in the logs indicating that the application server could not connect to the database - you can configure the database connection in the depconfig directory by editing the ewsconfig.xml file and then executing the deploy.bat batch file. Another common source of errors is when the deploy.bat file indicates that the tools.jar Java archive is missing - this message appears in the command prompt window when deploy.bat begins execution.

After sorted out all the errors and have the application running, you can browse to the application in the web browser and attempt to log in with the username "r5" and password "r5", which is the default account created within the application.

The installer could have been made to reduce the administration effort for installing the application, but once you've installed it, you can create a procedure manual for your team to follow the steps that you did for setting up the system.

Saturday, August 31, 2013

Code Normalization

When you hear about normalization, it is typically in reference to data models. However, code normalization is a way to take the concept and benefits of normalization from the database domain and to apply it to code. Code normalization is used to describe a wide variety of techniques, with the simplest being the use of a pre-processor to strip out comments and white spaces, and a more complex application of code normalization being used to reduce executable code to canonical forms that can be analyzed to detect obfuscated or mutating malware.

Sunday, August 25, 2013

CodeIgniter: "The upload path does not appear to be valid" error

The "The upload path does not appear to be valid." error when using the CodeIgniter upload library can be quite puzzling. The problem usually occurs when a call to "$this->load->library('upload', $config)" doesn't load the configuration settings, so adding the following statement after loading the upload library usually sorts out the problem (assuming your configuration array is named $config):

You can also choose to create an upload.php file within the config directory and place the $config array within that file instead of the call to the initialize function.


Friday, August 23, 2013

Enums (Enumerations) in ASP.NET MVC DropDownLists

Getting an Enum within an ASP.NET MVC DropDownLists can be performed using reflection if you do not want to have to create the entries manually. You can get SelectListItem objects from the Enum as follows:

var listItems = from MyEnumType e in Enum.GetValues(typeof(MyEnumType))
select new SelectListItem() { Text = e.ToString(), Value = ((int)e).ToString() };

You can then use the resulting object reference to pass to a SelectList constructor and use it within a DropDownList like this:

var selLst = new SelectList(listItems, "Value", "Text");

Further, you can use it within an ASP.NET MVC DropDownList in the manner described below.

In the controller, assign it to a ViewData item (you can use a View Model instead, if you prefer)

ViewData["VTypes"] = selLst;

In the view, use the ViewData item to obtain an IEnumerable object type (assuming you are using the Razor view engine):

@Html.DropDownListFor(mdl => mdl.VType, (IEnumerable)ViewData["VTypes"])

Sunday, August 18, 2013

Entity Framework: An object with the same key already exists in the ObjectStateManager

I attempted to obtain the current values of a database row to compare them with a value that I was setting using the Entity Framework. When all was set, I tried to update the database with the modified object using the following:
db.Entry(objNew).State = System.Data.EntityState.Modified;
...and that was when the Entity Framework threw an exception with the message:
An object with the same key already exists in the ObjectStateManager

The problem is that when I fetched an existing value, the object state manager had one object so when I tried to set the state of the other object to modified, it noticed that an object with the same key already exists. There are two ways to deal with this problem.

Solution 1: Update the existing object

This is a pretty straightforward solution. Instead of setting the state of the new object to modified, I change the state of the old object, but instead of setting each property manually, it can be done like this:
followed by a db.SaveChanges() call.
Solution 2: Detach the old object

To detach an object, you simply have to set the state to Detached, just as you would when you want to set the state of the new object to Modified. Here's how it is done:
db.Entry(objOld).State = System.Data.EntityState.Detached;
You can then update the database with the new object, as you would do normally.

Thursday, August 15, 2013

Linked List Data Structure

A linked list data structure is perhaps the simplest following an array. It consists of a set of elements wherein each element points to the next. It does not require a contiguous area of memory unlike an array. Adding to a linked list can be as simple as setting the new element as the first element of the list or finding the last item of the list and making the new item the last item. Removing an element requires searching for the previous element of the list, unless the element to be removed is the first item, in which case the removal is quite simple. Searching for an element is no simpler than an array, which requires a comparison with each of the elements. A variation of the sorted list, like a sorted array, makes searching for elements easier while adding complexity to the addition of new elements. However, addition of a new item to the middle of a linked list is much simpler than adding to the middle of an array - an array requires all subsequent elements to be shifted whereas a linked list requires the pointer of the previous element to be set to the new element and the pointer from the new element to be set to the next element. Linked lists are good for implementing stacks with addition and removal occurring from the head of the linked list.

ASP.NET Razor: Output String Without Encoding

If you are using the ASP.NET Razor view engine and have to output a string without encoding, you have to replace the @variable_name with an @Html.Raw(variable_name). Sure, it seems like additional effort to do it in the Razor view engine when compared to the <%: and %> in ASP.NET ASPX view engine but it is an edge case that you would barely encounter 20% of the time when building applications with ASP.NET.

Wednesday, August 14, 2013

ASP.NET HEAD runat server

The HEAD tag within an ASPX file typically has a runat="server" atttribute to make it into a server control. A lot of programmers wondered why this was necessary. Well, it is not but if you do turn it into a server side control, you get the ability to dynamically add tags into the HEAD tag and get URL resolution as well (and it provides the ability to use the tilda to generate absolute URLs). For example, the Page object has a Title attribute and you cannot use it unless you make the HEAD a server side control. Similarly, you can add meta tags 'programatically' instead of placing it within a markup - why would you want to do something like that is something the CMS folk can answer from their experience of getting the page information from a database of a content management system and using the ASPX markup as a mere template.

Tuesday, August 13, 2013

Apress: ASP.NET MVC 4 Books

If you're looking for a good book to read about and learn ASP.NET MVC, Apress has a pair of books on ASP.NET MVC 4 that are available on Amazon.

The book targeted at ASP.NET Web Forms developers is the Beginning ASP.NET MVC 4 book:

It explains the concept of the model, view, and controller components of the MVC pattern and how they are using in the ASP.NET MVC framework and discusses the use of AJAX and configuring routing. Essentially, you can gain knowledge about the use of the ASP.NET framework using this book. The examples are illustrative rather than ones you can follow along so if you haven't got ASP.NET programming experience, it could get difficult to try to code the examples yourself.

If you would like to go beyond the basics, the Pro ASP.NET MVC 4 book is for you:

This book has a 4.5 star rating (with 67 reviews) and explains design issues for you application when using the ASP.NET MVC framework and helps understand the concept of filters, provides an introduction to using custom view engines, dealing with advanced model binding issues, using APIs, and dealing with deployment issues. The examples are simple enough to follow along and that would leave you wanting to see more complex examples, but it does help you understand the concepts rather than leading you to the solution of every problem you would encounter.

Monday, August 12, 2013

Python Modules

Modules are used in Python to separate code into multiple files and thus make your source code more manageable. This presentation provides a quick guide to using modules in Python.

Decimal Numbers in HTML5 Input Number

The HTML5 number input element type helps eliminate the need to validate numeric input through client-side Javascript as the validation would be performed by the web browser. However, one common problem faced by web developers is that the number input element type indicates that any number with a decimal point is invalid input.

This is because, by default, the step for the number input element type is 1 therefore the validation enforces the use of whole numbers. You can enforce the number of decimal points by setting the step to a value such as 0.1 for one decimal place, or you can set step="any" to allow any number of decimal places. You would therefore have something like the following:

<input step="any" type="number" />

Saturday, August 10, 2013

ASP.NET MVC: Why Should I Move From Web Forms

Having used ASP.NET MVC quite extensively, I can tell you that ASP.NET Web Forms is quite good for prototyping. However, when you get to building Internet applications, ASP.NET MVC provides you with a lot of control over the markup of your application. Sure, it is more effort when you want to build the user interface and at times I did think that something I was building would have taken lesser time to build with ASP.NET Web Forms - quite possibly one of the reasons why Microsoft announced one ASP.NET, a statement that you can mix ASP.NET MVC and ASP.NET WebForms code within the same project.

ASP.NET MVC provides scaffolding (through code-generation) to reduce the effort involved in creating ASP.NET MVC user interfaces. Well, it is supposed to - it is still buggy when dealing with relationships between entities but when you have unrelated entities it works perfectly. This is most likely something that would be fixed in the next release or in one of the updates to Visual Studio. You can also take advantage of a wide variety of HTML/CSS/Javascript user interface components that you can use with ASP.NET MVC so if you need to build a user interface coherent with one built using PHP, Python, or Ruby, you don't have to create subclasses of the Label, TextBox, GridView, and ListView controls or add 'hacky' (seriously, doing a find-and-replace on the generated markup is an unnecessary CPU overhead) event handlers to alter the markup. The additional effort that you put into create the MVC views does pay off because with model binding, ASP.NET MVC can perform validation with nothing more than annotations (attributes) on your model. HTML 5 control rendering is also possible through adding attributes to your model. Sure, purists would argue that you shouldn't be adding attributes on your model to affect the presentation of your application but all you are doing is further describing the type of data being stored using the model and the view simply adapts (if you want it to).

I would also like to mention that when you do see performance benchmarks comparing a Hello World page in ASP.NET MVC, make sure that the benchmarks compared the ASP.NET MVC framework to another MVC framework - there are some comparisons of a Handler-like (ASHX) processing mechanism on other platforms to a Hello World on ASP.NET MVC and that just isn't fair - as soon as you use MVC, you've got routing and that adds additional processing to the application so you are bound to get lower performance scores when compared to a non-MVC framework.