Is MVC Dead? I don't think so!
Recently I came across a discussion that asked the question "Is MVC Dead?". It took me a bit by surprise. Over the last two years I was in charge of developing a responsive web-based line-of-business UI that would complement our existing Windows UI built with WPF (Windows Presentation Foundation) which uses the MVVM (model–view–viewmodel) pattern. The mission was to reproduce the powerful desktop experience in a web browser while reusing all the business and validation logic that was developed for the Windows UI. The new web-based application needed to be responsive, maintaining a great user experience with all functionality on any sized device. I did this with great success using ASP.Net MVC (model-view-controller). In all my experience and with all the people I worked with; – "Is MVC Dead?" No, I don't think so. Let me explain by taking you through the thought process and the design decisions we made as a team to accomplish this mission.
Architecture, Architecture, Architecture
Accelerator High Level Software Architecture Diagram.
First of all, I was fortunate that we had previously architected and designed the WPF application to consume services and have all validation and business logic centralized in non-visual C# classes. Take a look at our architecture diagram. For us great architecture is pivotal to future proofing your software and this project further proved that.
I have always grouped business logic into three categories: (1) Validation logic, (2) Business Processing logic and (3) View/State logic. Since we develop using .NET, let me go into some details regarding how we support these three categories.
- For validation logic, we use attributes on the properties defined in our entities. During the development of our WPF UI, we created validation attributes that can be easily added to properties in the entity. By creating wrappers around the WPF controls, we were able to build in some really cool intelligence that gave the user feedback based on the specific validation attributes. We even started using attributes to centralize how information was displayed to a user, which led us to group our attributes into either Display or Validation attributes. The power of these attributes is that they are centralized and data can be validated on the client as well as on the server. As a developer, I would not want to assume the services will be called by a UI that has properly validated the data.
- Once the data has been validated, the business processing logic takes over which runs on the server. Obviously, any issues during that process can result in an error that the UI can react to.
- The view model in our WPF world runs on the client and was designed to be able to set the state of UI controls including commands. for example, something as basic as setting commands to be enabled, disabled, or hidden based on data and context was coded in the view model.
Again, my mission was to reproduce the WPF desktop experience on the web while reusing as much of the business logic as possible in order to maintain great architecture and take advantage of that previous investment. So now that you have a background on our implementation of business logic, how did we accomplish creating a desktop-style line of business web application that reused this investment?
A Single-Page Application: Client-Side MVC, Server-Side MVC, or Both?
Since I was creating a line of business (LoB) application, I knew I needed to create a Single Page Application (SPA) as I wanted to allow an end user to determine what and how long information needed to stay in the browser view while allowing them to multi-task into other areas of the system just as they would with the rich WPF desktop experience. In this post, I can’t go into details regarding all the UX design decisions, but we have spent significant time on the user experience. It is, after-all, the first Pillar to Accelerating Software Development.
Because I was creating a SPA, I evaluated the popular client-side frameworks such as Angular and React. I worked with Angular (Version 1 at the time) for a couple days and found a critical limitation with the framework. My design needed to support loosely coupled modules/components that could be loaded independently as separate views within the same page. Angular v1 did not make it easy to support multiple views on the same page. (I believe support for this design has been added to Angular Version 2.) Because of this limitation, I moved my attention to React which is more focused on the view. For my client-side needs, I ended up creating my own framework that catered more specifically to our needs, using React where and when needed.
I also decided that it was best to have a balance between the responsibility of the client and the server as well as support a high level of code reuse. I was against coding business logic in JavaScript and then coding it again on the server in C# and needed to find a solution for this. Since the application I was bringing to the web was using .NET, I knew I wanted to use ASP.NET MVC for my server side MVC framework. This hybrid approach allowed me to have a client and server side MVC framework. Once the main page layout was rendered by MVC, I was able to deliver module/component views to the client via AJAX calls to the controller. This allowed me to create a Single Page App and leverage the server-side scripting capabilities of ASP.NET MVC for my individual component views. The design worked out perfectly and allowed me to utilize the power of a server-side MVC framework and the custom jQuery plugins I created that provided the data binding and routing I needed for the client-side MVC framework.
Pulling it all together
If we just consider validation logic for a moment, I knew I wanted to reuse all the validation logic that was written in C#; but, of course, that can’t run in the browser. And I didn’t want to have just server-side validation logic. I wanted to make sure that as much validation logic as possible (or that made sense) was delivered to the client. In the WPF framework I created intelligent WPF UI control wrappers that worked with attributes in the entity. So, I decided to try this same technique out in the Web world. My first step was to refactor the C# attributes to inherit and extend the MVC data annotations attributes. This allowed me to tap into some of the development that Microsoft already did with data annotation attributes.
I was also able to wrapper the html controls I was using with some intelligence to react to the attributes on the properties within my entity in the same way that WPF did. The end result was that I now had validation and display attributes that played nicely with both the WPF and ASP.Net MVC world. The Web UI controls use a combination of JavaScript, custom jQuery plugins and HTML data attributes. The HTML data attributes are applied on the server-side after evaluating the various attributes in the entity and delivered to the client as view components via an AJAX call. I accomplished the ability to centralize my validation logic that can now be used by both WPF and ASP.NET MVC that also gives me the ability to have client-side and server-side validation. When developing Web applications, I was never a fan of coding validation logic in JavaScript and then having to recode the same logic in C# for the server side. This solved my problem.
The next hurdle was to reuse the C# View model display state business logic. This is code that sets the state of the UI controls including the commands. For the time being, I was able to tap into this logic by creating a couple generic services that pass in the current client state via an AJAX service call and allows the view model to change the state. One of the concerns I had at the time was whether this approach would be too chatty as the client is being triggered to call the server to determine if state should change. So far it hasn’t been a problem and has surprisingly worked out very well. I can always revert back to coding some of the state in JavaScript, but if I can reuse code without an impact to performance or to the User Experience in general, I will opt for the centralization of code.
Is MVC dead? I don’t think so.
In my case, a client-side MVC framework just wasn’t good enough and I needed the power of a server-side MVC framework as well. Tapping into the power of both provided me a lot of additional benefits. At the end of the day, I think there can be a happy medium between client and server coding. There are pros and cons to having a very thick JavaScript client as well as to having everything on the server. I was able to take the good from both sides and create a very powerful line of business application that will be easy to maintain and scale. You can try the ASP.NET MVC line of business out for yourself. Surround has posted several demos. Please feel free to reach out to us if you have further questions or want to talk about our design approach in more detail.