From WebForms to MVC, the first 10 minutes
What’s this? A post about WebForms?
Is it 2002 all over again? Is GeoCities still going strong? Are we all about to invest endless hours building SOAP services and learning XML?
No, no we’re not.
But, just because it feels like everyone is off building shiny new apps using ASP.NET Core 2.x the truth is there are still plenty of us spending at least some of our days working with “legacy” (and sometimes not so legacy) apps built using WebForms.
And if you’re trying to move to something else at this moment in time you’d be forgiven for feeling overwhelmed.
The web is awash with information covering every topic you could possibly imagine (and then some)…
- SPAs (Angular, React etc)
- MVC 5
- MVC Core
- Razor Pages
- .NET Framework
- .NET Core
Where do you start?#
We’ve got to start somewhere so let’s begin with performing a common WebForms task using ASP.NET Core MVC…
If you’re new to MVC you could be forgiven for feeling confused.
There’s a lot of terminology to get to grips with, where Webforms had one or two moving parts MVC has several.
But when you take a step back and explore what WebForms is doing under the hood it becomes easier to translate that to MVC.
Change label text via a Postback#
WebForms did its best to act like a Windows app which happened to run in the browser but in reality it uses a little smoke and mirrors to hide what it’s actually up to.
Here’s an example.
Create a page with your button and label, something like this…
Create a handler to handle the button click event, set the new property value for the label and voila, the label is updated when you click the button.
Unpicking the abstraction#
This might look and feel like a windows app running on the desktop but “under the hood” ASP.NET is simply making GET and POST requests from the browser to the server.
Yep, it’s doing exactly what every other web application ever written does, make requests to the server.
Here’s what’s actually happening.
You request /SimpleLabel in the browser
Your browser makes an HTTP GET request
ASP.NET handles the GET request and routes to the corresponding WebForm (SimpleLabel.aspx)
ASP.NET renders html for the label/button controls and returns it to the browser
The rendered html includes a form which will be submitted when the button is clicked
You click the button
The browser makes an HTTP POST request to the server (submits the form)
The “btnChangeLabel_Click” event handler runs, changing the label’s text
ASP.NET re-renders the html (with the new value for the label) and returns it to the browser
You see the new value in the browser
So you see, it’s not actually magic, just an HTTP GET and an HTTP POST.
How does MVC do it?#
Now let’s take the exact same requirement and do it with MVC.
The main difference is that you are no longer quite so abstracted away from the HTTP requests and HTML markup that your app is ultimately going to use.
Instead of a WebForm with ASP.NET controls, you need a view with (mostly) standard HTML tags.
Index.cshtml
The only non-html part of this markup is the first line and the subsequent reference to @Model.Greeting
which is Razor syntax to enable you to take data coming from the server and mix it up with your HTML.
Now we have our button and a greeting, but how do we get to this in a browser?
We can’t, not without a controller to handle requests (from the browser) to our application.
SimpleLabelController.cs
Now we’re getting somewhere, a request to go to /simplelabel
in the browser will be routed to our Get
action where we return our view (index.cshtml).
We also return an instance of our view’s model (SimpleLabelModel) which (if you’re interested) looks like this.
SimpleLabelModel.cs
Remember this line in the view?
That ensures the value we just set in the Model (“Welcome one and all”) is displayed as a span in the rendered HTML.
NOTE
How does MVC know which requests go to which controller?
Your MVC app can handle any requests you throw at it but you need to send them somewhere right?
In this example we’re using attribute routing.
[Route("[controller]")]
This attribute on the controller means the first part of the URL will be the name of the controller e.g. https://<your-site-here>/SimpleLabel
.
[HttpGet("")]
This attribute on the controller action (the method in that controller) simply ensures that any get requests to https://<your-site-here>/SimpleLabel
will end up here.
If we’d done this instead…
[HttpGet("fancy")]
… the url to get to this method would be https://<your-site-here>/SimpleLabel/fancy
Now what about handling that button click?
The button will submit the form, which will post back to /simple-label
but wait, we don’t have any controller action to handle it!
SimpleLabelController.cs
And there you have it! Click the button, the browser submits the form (via a POST) and the corresponding controller action returns a new instance of the model with our new and improved greeting.
Putting it all together#
Here’s the MVC flow then…
Legacy .NET web apps causing you grief?
Build modern, reliable web applications, faster with .NET and Blazor.
Build better .NET web appsMore moving parts#
Looking back at this you can see that MVC requires you to handle more moving parts (controllers, views and view models).
But with this increased complexity you also get more freedom to craft your routes, your html, even to start adding javascript to your views where it improves the user experience.
Before you go#
Get a handy PDF showing the two flows (WebForms and MVC) next to each other, plus source code for both examples.
Legacy .NET web apps causing you grief?
Build modern, reliable web applications, faster with .NET and Blazor.
Build better .NET web apps