The first version of ASP.NET was released 17 years ago in early 2002 as part of the version 1.0 of the .NET Framework. During part I of this series of articles we took a look at its initial design, one providing a better web platform than classic ASP and ActiveX, one that could feel familiar to existing Windows developers.
Read - The History of ASP.NET – Part I
With the web being one of most fast-paced platforms, it’s no surprise to look back and see that the framework had no option but to adapt to the multiple changes that happened on the web and its surrounding technologies since its initial launch. But of course, this wasn’t so obvious while changes were in flight at the time!
In this second part of the series, we will now look at how those changes influenced the development of ASP.NET MVC and ended up transforming ASP.NET into a much more flexible framework composed of multiple libraries that solved different problems.
MVC - A new direction (2008-2014)
Changes in the web were happening fast and ASP.NET was somewhat ill prepared for them. We have already discussed how the Web Forms abstraction meant the reality of the web and HTTP, HTML and JavaScript was hidden from developers. While ASP.NET worked well in the old 2002 world of server-centric web applications and XML-based web services, advances in web development meant the abstraction became even more leaky.
On one hand, increasing amounts of functionality were being moved to the client side as JavaScript code. While ASP.NET had tools aimed at JavaScript, particularly once Microsoft AJAX became part of the framework, the focus was still predominantly on controls.
It was possible to write JavaScript and add it to a page using the ScriptManager but it wasn’t easy to work around the PostBack model unless building SPA applications using ASMX or WCF services, something for which JavaScript wasn’t fully ready. It was also possible to add custom JavaScript into custom Server Controls, but the process was cumbersome.
In the end, many developers mostly used controls like the UpdatePanel, and the controls/extenders part of the AJAX Control Toolkit, instead of writing JavaScript.
On the other hand, JSON became the most common payload format for AJAX requests, due to its smaller size compared to XML and the ease of integration with the JavaScript code that typically consumed them. Both ASP.NET and WCF focused on XML-based SOAP services, with support for JSON over HTTP added later. Both ASMX web services and WCF services required to be specifically configured to handle JSON over HTTP.
But that wasn’t all.
Since Web Forms abstracted the web for ASP.NET developers, directly working with JSON was a cumbersome afterthought without first class support in the framework.
In summary, we had a leaky Web Forms abstraction combined with the increasing importance of JavaScript and JSON, at the time when frameworks such as Ruby on Rails exploded.
Introducing ASP.NET MVC
Microsoft was aware of the situation, announcing in late 2007 that they were working on a new framework called ASP.NET MVC where they were trying to address these concerns. The framework would be open sourced and explicitly designed with testability and pluggability in mind. Microsoft went as far as sharing the following list of key design goals as part of the announcement:
- Follows the separation of concerns design principle
- Grants full control over the generated HTML
- Provides first class support for TDD (test driven development)
- Integrates with existing ASP.NET infrastructure (Caching, Session, Modules, Handlers, IIS hosting, etc.)
- Pluggable. Appropriate hooks to be provided so components like the controller factory or the view engine can be replaced
- Uses the ASPX view engine (without View State or postbacks) by default, but allows other view engines to be used like the one from MonoRail, etc.
- Supports IoC (inversion of control) containers for controller creation and dependency injection on the controllers
- Provides complete control over URLs and navigation
It is worth highlighting that this wasn’t the first attempt at a cleaner web framework for .NET. We have already seen that Microsoft themselves provided guidance on implementing patterns like MVC or the front controller back in 2003. The .NET community also worked on providing its own alternatives, with MonoRail (part of the Castle Project, and inspired by Ruby on Rails) being the most prominent one. In fact, this is one of the usual criticisms Microsoft faced for its attitude towards open source. Rather than embracing and supporting open source initiatives, they would build and promote their own.
In the words of Steve Naidamast:
MVC had been around for a long time as a pattern, and the .NET Community had it as well in the guise of the “Castle Project” where it was known as “MonoRail”. It was simply never regarded by anyone as anything substantial until Microsoft began promoting it with their own version of MVC, which appeared to be an exact copy of what the “Castle Project” people had already developed.
Eventually, version 1.0 of the framework was released in March 2009. It shipped as a standalone release separate from the .NET framework, which stayed on its 2-year release cycle. Its code was available in CodePlex and used the MS-PL license, with broad rights to modify and redistribute the code. This marked an important milestone in Microsoft’s attitude towards open sourcing.
Developers now had an alternative from Microsoft that embraced the web and didn’t try to hide details such as HTML, HTTP, JavaScript or its stateless nature. Instead, it provided the tools and flexibility needed to work with them.
An HTTP request would now be served by a specific Action method of a Controller class. The URL was matched to the controller and action through a new routing module that allowed convention-based routes with the default /controller/action. The action method would then perform the necessary logic needed to serve the request and return an Action Result, where rendering a View was only one of the results. Views would be ASPX templates located in a different folder from the controller.
Figure 1, Request lifecycle of an ASP.NET MVC application
The customary Hello World example could contain a HelloWorldController class located in the Controllers folder:
public class HelloWorldController : Controller
{
public ViewResult Index()
{
return View((string)null);
}
[HttpPost]
public ViewResult Index(String name)
{
return View(name);
}
}
A corresponding view Index.aspx would be in the Views/HelloWorld folder. Initially the framework used the ASPX view engine, which made mixing C# code and HTML not as nice as current Razor code can be:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<String>" MasterPageFile="~/Views/Shared/Site.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% if (Model != null) { %>
<p>
Hello <%=Html.Encode(Model) %> !
</p>
<% } %>
<% using (Html.BeginForm()) { %>
<p>
<label for="name">Name:</label>
<input id="name" name="name" type="text">
</p>
<input type="submit" value="Say Hi" />
<% } %>
</asp:Content>
Common layout and HTML structure were achieved through Master Pages, with Views specifying the Master Page in its @Page directive. In this example, there would be a shared master page Site.Master.aspx in the Views/Shared folder:
<%@ Master Language="C#" AutoEventWireup="true" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>ASP MVC 1.0</h1>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</body>
</html>
The framework didn’t need to be told where the controllers or the views were located. The idea of conventions was built into it and used for the routing and controller/views location.
The default route /controller/action was provided, and the framework would automatically look for a controller class inside the Controllers folder that matched the name from the URL. It would then look for a method of that controller whose name matched the one in the URL. Similarly, the framework would look for views with the right name inside the Views folder. Developers were also free to replace these conventions with their own, customizing the routes or wiring their own controller factory and/or view engine.
Overall, a Hello World example like this, and even simple CRUD-like functionality looked more complex and harder to implement than its Web Forms counterpart. This is why scaffolding, tooling to automatically generate pages and controllers (an idea imported from Ruby on Rails) became so important.
ASP.NET MVC or Web Forms?
Development in MVC continued and its 2.0 version was released in March 2010, a month before .NET Framework 4.0 was released. ASP.NET 4.0 further refined Web Forms, amongst other new features, it was now possible to disable View State except on those controls where you explicitly enable it and it was also possible to use the routing module with Web Forms pages.
Microsoft faced a tough challenge. It had a significant investment and user base with Web Forms, while at the same time, it had to shift towards MVC as their future strategy. The position adopted since MVC 1.0 was that both frameworks were compatible and had different strengths. Web Forms was positioned as a RAD platform due to its set of controls and stateful nature, allowing developers to quickly build applications without dealing with the complexities of the web.
Regardless of how Microsoft positioned both frameworks, the reactions in the community of ASP.NET developers were mixed. Some were enthusiastic about it since its announcement and saw it as the change ASP.NET needed, something akin to what the ALT.Net movement had been preaching about.
For many who worked regularly with Web Forms, skepticism was the initial reaction, considering Web Forms the mature and stable framework to build anything cost-efficiently and MVC as the experiment for purists and experts. We can read an example here and another one here:
The problem with MVC is that even for "experts" it eats up a lot of valuable time and requires lot of effort. Businesses are driven by the basic thing "Quick Solution that works" regardless of technology behind it. WebForms is a RAD technology that saves time and money. Anything that requires more time is not acceptable by businesses.
Time/money are the greatest reasons why webforms would be chosen over MVC. If most of your team knows webforms, and you don't have the time to get them up to speed on MVC, the code that will be produced may not be quality. Learning the basics of MVC then jumping in and doing that complex page that you need to do are very different things. The learning curve is high so you need to factor that into your budget.
The complexity and learning curve of MVC was highlighted as one of its disadvantages, since ASP.NET developers would need to write much more code to achieve the same functionality they got using the Server Controls and View State. In the words of Rick Strahl or in this answer:
I’ve seen an early build of the framework and it’s not really clear to me how to effectively handle more complex pages […]. I have built several Web frameworks in the past that use a similar approach to MVC and while you can easily do many simple things, in my experience this approach really starts falling apart when you have pages that contain many different and somewhat independent components. Managing this complexity through a controller-based approach that manages no state for you is much more difficult than what Web Forms provides today.
Since, you are not using WebForms you cannot use any ASP.NET control. It means if you want to create a GridView you will be running a for loop and create the table manually. If you want to use the ASP.NET Wizard in MVC then you will have to create on your own. […] you need to keep in mind that would you benefit from creating all the stuff again or not? In general, I prefer Webforms framework due to the rich suite of controls and the automatic plumbing
Another point that generated some push back was the move back to have code mixed with markup in the views, seen as a step back to the classic ASP days that Web Forms moved away from. We can find some of these examples in the answers to this Stack Overflow question:
Now someone in their great wisdom (probably someone who never programmed classic ASP) has decided it’s time to go back to the days of mixing code with content and call it "separation of concerns".
The biggest downside of MVC is we are going back to the days of ASP. Remember the spaghetti code of mixing up Server code and HTML??? Oh my god, try to read an MVC aspx page mixed with javascript, HTML, JQuery, CSS, Server tags and what not...
There were also concerns about giving up the existing investment in Web Forms like knowledge, Server Controls, tooling and infrastructure in favor of a completely new framework. For companies that had invested heavily in Web Forms, this wasn’t an easy decision.
To me, these initial reactions, and particularly the consensus amongst them about the complexity of MVC and the web without the Web Forms abstraction, prove that Microsoft had to make the move into MVC. This question contains the perfect example:
How would that work? No viewstate? No events?
These are the symptoms of a community of developers about to fall behind with the web, right at the time when a good understanding of HTML, HTTP and JavaScript would become vital skills for any web developer!
And let me tell you something, I was one of them.
Around this time, I had been working with Microsoft technologies for about 5 years. I did desktop development with VB6 and Win Forms, WCF SOAP-based services and the occasional internal site in ASP.NET.
I remember clearly going through the MVC 2 docs while trying to build an example site and being annoyed at the complexity of it. I had a particularly hard time understanding that the web was stateless and managing state between browser and server was hard! My instinct told me that when some UX event fired you should be able to run code in response to it, code which had access to the current state. This worked well in Win Forms and was simulated in Web Forms but clashed frontally with MVC and its unashamed exposure of the HTML, HTTP and JavaScript realities of the web.
At the same time, I hated the few Web Forms applications that I had seen at work (which we managed to transform into piles of spaghetti code-behind messes that were impossible to follow) and knew there must be a better way. Even after I was a convert to MVC, it still took me years to adapt to the harsh realities and limitations of the web after years of Windows development!
Outside of Microsoft, after jQuery was released in 2006, it quickly became the de-facto client-side library for DOM manipulation and AJAX, so much so that even Microsoft ended including it in ASP.NET project templates.
Initially, client-side code consisted of a collection of jQuery event handlers tied together more or less elegantly. But as the shift of logic to the client continued, client-side JavaScript frameworks emerged and tried to provide some structure. By 2010 we already had 3 major frameworks competing for our attention: Backbone, Knockout and AngularJS. Even Microsoft themselves caused another stir by releasing the open source project TypeScript.
Having a server-side framework that played nicely with these client-side frameworks, giving full control over HTML, CSS and JavaScript, and with first class support for AJAX requests was necessary for ASP.NET to remain relevant.
It seems that MVC arrived at the right time!
ASP.NET MVC is here to stay
As MVC continued its way forward, the skepticism among ASP.NET developers morphed into confusion. Ruby or PHP developers used to deal with HTML and HTTP would have an easier time picking up the framework, but a traditional Web Forms developer was confused by its apparent complexity and lack of functionality compared to Web Forms. And as soon as the framework lost its “experimental” tag in the eyes of many, forums, blogs and magazines would start discussing the right approach as to when and how to adopt MVC.
The development cycle of MVC continued to be independent of the .NET framework, with MVC 3 released in early 2011. This was a major milestone for MVC that improved the scaffolding features and introduced the Razor view engine, finally replacing the old ASPX view engine. Another highlight was the release of NuGet which finally brought a package manager to the .NET community, similar to the existing RubyGems or NPM which made the Ruby and Node.js open source ecosystems thrive.
Releasing and using open source libraries for .NET had never been easier!
Sure, it was possible to use open source libraries earlier, but most companies relied either on their in-house libraries or Microsoft ones, with Web Forms controls such as Telerik being the one common exception.
NuGet changed this scenario!
Furthermore, NuGet was the perfect match for MVC and its pluggable nature.
Discussions raged about which dependency injection library was the best, or which mocking framework should one use, or whether NHibernate was better than Entity Framework (although Microsoft would keep creating their own libraries, like Unity or EF, rather that supporting the open sourced ones). One could read the NuGet package of the week column from Scott Hanselman, run the NuGet install command and have it working on your website in minutes.
# This was the future!
Install-Package MiniProfiler
It was around this time, with MVC 3 as the latest iteration, that many developers and companies started to realize MVC was here to stay. Slowly, companies tiptoed into MVC with low-risk projects or proof of concepts, and developers were getting used to it. As both companies and developers gained experience with it, MVC began to consolidate as the default choice for new developments.
Even more importantly, MVC succeeded in enabling separation of concerns and TDD. The SOLID principles, dependency injection and unit testing became part of the common vocabulary of ASP.NET developers! These were not new, and certainly not impossible in the past, but they became relevant and broadly accepted whereas before they were a struggle of an informed minority.
But that wasn’t everything. Microsoft released Web Pages as an attempt to merge the concept of Web Forms with the Razor view engine and other MVC features, together with WebMatrix, a free tool bringing a simplified IDE and IIS Express together.
Meanwhile the ever-increasing popularity of client-side JavaScript frameworks and the advent of mobile applications multiplied the need for HTTP services, with REST (Representational State Transfer) becoming the new buzzword.
It’s no surprise then that mobile and REST services were the major topics when ASP MVC 4 was released in mid-2012. A new mobile template that used jQuery mobile was introduced, as well as the Display Modes, which allowed the framework to automatically select between desktop/mobile versions of the same view based on the browser’s user agent. However, the real star of this release was a new framework called Web API, introduced to simplify the creation of REST HTTP services by adapting the MVC architecture (but still being a different framework). Controllers, Filters and Routes were all known building blocks by then, which meant anyone using MVC would find themselves at home with Web API:
public class ProductsController: ApiController
{
public IEnumerable<Product> GetAllProducts()
{
return repository.GetAll();
}
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return item;
}
public Product PostProduct(Product item) { ... }
public void PutProduct(int id, Product product) { ... }
public void DeleteProduct(int id) { ... }
}
Shortly after, an update to MVC was released that introduced SPA (Single Page Applications) project templates using frameworks like Knockout, AngularJS or Backbone. The template combined both MVC and Web API with different client-side libraries, further moving the logic to the client.
By then, the ASP.NET team was well used to frequent releases introducing updates and new libraries. During 2012, they further improved ASP.NET by releasing the SignalR library as a NuGet package. This gave developers a tool that allowed them to easily implement real-time functionality in ASP.NET applications.
And with SignalR, the extended ASP.NET family was complete.
One ASP.NET
The refinements to ASP.NET continued in late 2013 with the release of version 4.5.1 of the .NET Framework. In this release Microsoft repositioned all the technologies now part of ASP.NET (i.e. Web Forms, MVC, Web API and SignalR) as components under the One ASP.NET umbrella. A unified project template in Visual Studio now acted as the entry point for all the different components of ASP.NET, with the idea being that developers could mix and match the different frameworks and find the right fit for their requirements.
Figure 2, All the frameworks rebranded as One ASP.NET
Web API reached its version 2.0 with this release. Amongst other features, the support for OData (Open Data Protocol) was improved, a specific package to implement CORS (Cross-Origin Resource Sharing) was added, and above all, the now ubiquitous attribute routing was introduced:
[Route("api/books")]
public IEnumerable<Book> GetBooks() { ... }
At the same time, MVC 5 was released. It received the same attribute routing as Web API, scaffolding support was improved, a new library called ASP.NET Identity for authentication was released and the request lifecycle was refined with separated filters for authentication and authorization.
The fact that the default project template was updated with Bootstrap 3 is a great excuse to take a look at the evolution of the MVC home page:
Figure 3, the evolution of the MVC home page from MVC 3 (top) to MVC 5 (bottom)
Even Web Forms continued receiving new features. Interestingly, most of these features was aimed at bringing Web Forms closer to its MVC cousin. Developers could now use model binders, data annotations, routing or unobtrusive JavaScript that began its life as MVC features.
Conclusion
ASP.NET reached 2014 in good shape, with several libraries offered under the One ASP.NET umbrella to suit different web application needs. You might not have been the only one who thought the framework had reached its full potential and would remain stable for several years.
Outside of ASP.NET, React arrived in 2013 and instantly became one of the SPA frameworks to consider, while Node.js and the NPM ecosystem had experienced an explosive growth. In fact, many were enjoying building web applications with Node.js thanks to lightweight frameworks like Express, based around the idea of a request pipeline of middleware functions. So much so that the MEAN stack (MongoDB, Express, AngularJS and Node.js) became another buzzword of the era.
As we will see in the next article (Part 3), the ASP.NET team had much bigger plans for ASP.NET than incremental improvements. They could see the potential of open source and multi-platform development, and were no strangers to the benefits an open source community could bring to its framework.
Stay tuned for the last part in the series to read about the ASP.NET Core design and evolution!
Update: Part III has been published. The History of ASP.NET – Part III (ASP.NET Core).
This article was technically reviewed by Damir Arh.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Daniel Jimenez Garciais a passionate software developer with 10+ years of experience who likes to share his knowledge and has been publishing articles since 2016. He started his career as a Microsoft developer focused mainly on .NET, C# and SQL Server. In the latter half of his career he worked on a broader set of technologies and platforms with a special interest for .NET Core, Node.js, Vue, Python, Docker and Kubernetes. You can
check out his repos.