6
votes

MVVM pattern in WPF has a strong emphasis on completely separating the ViewModel from the UI, and ideally has nothing or very little in the code-behind file. This allows to re-use the ViewModel for different types of interface.

MVVM pattern in Razor Pages has the code-behind as the ViewModel and is tightly coupled with the web logic with OnGet and OnPost methods.

Thus, the carefully-crafted decoupled WPF ViewModel cannot serve as the Web ViewModel (or perhaps can be used from the web page Model?)

Is there something I'm missing, and why is there such a difference between MVVM in WPF (decoupled) and MVVM in Razor Pages (coupled)?

If we were to apply the Razor Pages approach to WPF, then the code-behind would become the ViewModel -- which I've never seen anyone recommend.

2
As far as I know, MVVM is about decoupling Models from Views, not ViewModels from Views :\vasily.sib

2 Answers

4
votes

To make things clear: WPF introduces a coupling between the view and the view model the same way Razor Pages does. The view model is a data representation layer in order to break the dependency between the view and the model. So the view can be changed without modifying any models. The view model itself is then coupled to the model since it fetches the required data (e.g. from a service or data base). This behavior is realized in Razor Pages in a unified pattern by having the view models implement the abstract PageModel and by following a convention by providing the appropriate optional action handlers (e.g. OnGet()). Those handlers will be invoked by the framework anytime a HTTP request was issued for the page. You would fetch or manipulate model data based on the request method (e.g. GET, DELETE, POST, PUT, ...) and then present it to the view. The convention describes the naming pattern of those handlers so that the framework can identify them.

So you'll find the same degree of coupling between the layers in WPF MVVM and Razor Pages MVVM. Since the view model in RazorPages encapsulates the context of a specific page the source file naming follows a naming convention ("page name.cshtml.cs") to make the relationship visible in your filesystem. It's not a code-behind file like the partial class file of a view in WPF.

1
votes

I'm not sure why you insist on using Razor Pages, when there is MVC (Model-View-Controller).

You should use the MVC pattern instead. You get the same razor syntax but decoupled.

Razor Pages were introduced as a form of successor to WebForms (which itself tried to mimic Windows Forms, which isn't about decoupling neither).

If we go a few years back in history, MVVM was to use the full power of WPF's Two-Way Model binding, which acts as a separate layer between the UI and Application layer where one can put presentation logic in (logic tightly coupled to the Presentation, which is an UI concern rather than application layer which is decoupled from the UI).

For that reasons the MVVM's ViewModels also have (additionally to properties for Model Binding), things like Commands and may be Navigation aware (i.e. via Prism's INavigationAware interfaces).

In this context, ViewModels aren't of much value in server-sided web applications, because HTTP by itself, is stateless where ViewModels maintain a state.

Thus the ViewModels in MVC are simply reduced to DTOs (Data Transfer Objects), which has basic validation (through validation attributes). ViewModels in MVC Applications don't have any presentation logic, due to the fact its rendered into HTML and most presentation Logic happens outside via JavaScript (what happens when a button is clicked, how to format a date or currency for a user).

That being said, you don't really need full-fleged ViewModels in an ASP.NET Core application, at least not for the server-sided part. However, if you are using a client-sided technology (Angular, Vue.js, React) you may utilize ViewModels to enhance the functionality and decouple it from the View.

In fact, angular components are pretty much ViewModels and fulfill the same task as ViewModels in MVVM pattern do (one can inject services into it, has 1-way or 2-way bindings, input validation and one puts presentation logic in them).

TL;DR: You don't really need ViewModels as they are defined in MVVM, just DTO-like classes to make consuming them in the (Razor)View Template easier. And don't use Razor Pages for decoupling.