4 min read

ASP.NET Web Forms and Vue

Having recently done some work in ASP.NET Web Forms, I was reminded that sometimes it's a better approach to add some features to an application in advance of a complete rewrite. Other inspiration, that I came across while investigating the topic, was this former MSDN Magazine Article: https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/april/data-points-adding-new-life-to-a-10-year-old-asp-net-web-forms-app

While I would like to do a full-scale rewrite of these applications, it's not feasible at this time. This is some exploratory work for what might I think is a good balance (if it turns out of course). The idea that I have is to nest a SPA framework into more complex pages to get the convenient coding benefits. It's not perfect, as it must be done on a page-by-page basis, but it represents a meaningful leap forward from the starting point.

I selected Vue.js because it seemed like the easiest to slot into an existing application and page without making fundamental changes to the application (as would be required of more opinionated frameworks).

Getting Started

I assume that you've got Visual Studio 2019 installed with the right packages. Unfortunate, while I do use Visual Studio on both Windows and MacOS, this article (and Web Forms development in general) only applies to Windows.

First Steps

This assumes that you've got a project (hopefully in a Master page - if not, that's another good refactoring start) available. I wrote the example just using the generated template from Visual Studio 2019 (nice to see it's still an option).

A new ContentPlaceHolder is required for placing the script into the Master page:

<!-- The rest of the site content preceeds this -->
</body>
	<asp:ContentPlaceHolder ID="ScriptContent" runat="server">
    
    </asp:ContentPlaceHolder>
</html>
Site.Master - new ContentPlaceHolder for holding the Vue application scripts

nuget Additions

Either Package Manager Console or the Manage Nuget Packages UI, and add the Vue package:

Add vue Nuget package

I confirmed the nuget package reflects the most recently published release version of vue (2.6.1 at the time of writing, and of course there are no guarantees that it will be maintained going forward).

First Vue Web Form

After that it's time to generate the first sample page, as shown here (just right-click your project and Add a New ASPX file). This is the code to add to the generated page (MainContent contains the template/markup and the ScriptContent contains the app initialization script that will actually do the binding):

https://gist.github.com/mathewgrabau/a8884c1d33edd6c943470e4931e96429

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="FirstVuePage.aspx.cs" Inherits="VueWebForms.FirstVuePage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <h1>First Vue Page</h1>

    <div id="app">
        {{ message }}
    </div>

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ScriptContent" runat="server">
    <script type="text/javascript">
        window.onload = function () {
            // Initialize the Vue app
            var app = new Vue({
                el: '#app',
                data: {
                    message: 'Hello from Vue!'
                }
            });
        };
    </script>
</asp:Content>

Given the integration into a server-side file ASPX file, the it certainly looks different from the. It shouldn't look too strange though, as it has all the Vue basics in there (https://vuejs.org/v2/guide/#Declarative-Rendering).

Running the Sample

Once the page is configured, compile/run the site and get the following when navigating to FirstPageVue.aspx (note that new routing in updated versions of Web Forms allows for visiting FirstPageVue instead):

Vue successfully integrated

Event Handling

Client-side event handling is the area where a front-end framework such as vue shines. The simplicity inherent in binding events to handlers is undeniable.

Adding a binding for a client side event is very straight-forward:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="EventHandlerPage.aspx.cs" Inherits="VueWebForms.EventHandlerPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <h1>Event Handler Test</h1>

    <div class="row" id="app">
        <div class="col-md-4">
            The last time of the click was: {{ lastClickTime }}
        </div>
        <div class="col-md-4">
            <button class="btn btn-primary" type="button" @click.prevent="clickHandler">Update Date</button>
        </div>
        
    </div>

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ScriptContent" runat="server">
    <script type="text/javascript">
        window.onload = function () {
            // Initialize the different applications
            var app = new Vue({
                el: '#app',
                data: {
                    lastClickTime: null
                },
                methods: {
                    clickHandler() {
                        this.lastClickTime = new Date();
                    }
                }
            });
        };
    </script>
</asp:Content>

Note that without the .prevent modifier the mandatory form (for using a server-side page) will submit unless the button has a type="button" attribute on it.

The resulting page and the event response are shown below:

Event handling sample on initial load
After clicking the button

As shown, clicking the button results in the event being handled and updating the label.

Conclusions and Next Steps

Projected next steps/plans for this series are (in no particular order):

  • Create a sample with vue-router and the other components that are typically found in a vue application
  • Attempt to configure styling for the site based on the Vuetify Material Design components
  • Test integration of the Vue components for Syncfusion's EJ2 product (https://www.syncfusion.com/vue-ui-components)
  • Investigate the implications of the built-in form on server-side pages and options for working with/around that
  • Integrate axios and test AJAX with WebMethods (including form posting)