Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
813 views
in Technique[技术] by (71.8m points)

architecture - Is there a reason to use ViewModel in Blazor Server Side?

I'm starting to develop a Blazor Server Side application and my idea is to use :

My folders structure will look like this :

Features
  Feature 1
     XXXView.razor : the view
     XXXView.razor.cs : the partial class
     XXXView.razor.queries.cs : contains the queries (ex : GetCustomer) used by the view
     XXXView.razor.commands.cs : contains the commands (ex : SaveCustomer) used by the view        
  Feature 2

My question is the following : in this kind of architecture, is there a good reason to use a ViewModel (as in asp .net MVC projects) instead of using the entity directly in the view ? The code below is an example of what I would do without using ViewModel.

public partial class UserEditView : EditableComponentBase
{
    [Parameter] 
    public long? Id { get; set; }

    [Required] 
    public string Name { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (this.Id.HasValue)
        {
            UserEntity user = await Mediator.Send(new GetUserQuery(this.Id.Value));
            this.Name = user.Name;
            this.Title = $"Change info of {user.Name}";
        }
        else
        {
            this.Title = "New user";
        }

        await base.OnInitializedAsync();
    }

    protected override async Task Save()
    {
        UserEntity user = this.Id.HasValue ? await Mediator.Send(new GetUserEditViewQuery(this.Id.Value)) : new UserEntity();
        user.Nom = this.Name;

        await Mediator.Send(new SaveUserCommand(user));

        Close();
    }
}

with GetUserEditViewQuery returning an entity with all information needed fetched or in lazy loading.

The code below is an example of what I would do if I use ViewModel.

 public partial class UserEditView : EditableComponentBase
{
    [Parameter] 
    public long? Id { get; set; }

    public UserViewModel User { get; set; } = new UserViewModel();

    protected override async Task OnInitializedAsync()
    {
        if (this.Id.HasValue)
        {
            this.User = await Mediator.Send(new GetUserEditViewQuery(this.Id.Value));
            this.Title = $"Change info of {this.User.Name}";
        }
        else
        {
            this.Title = "New user";
        }

        await base.OnInitializedAsync();
    }

    protected override async Task Save()
    {
        await Mediator.Send(new SaveUserCommand(user));

        Close();
    }
}

with GetUserEditViewQuery returning a ViewModel containing all information needed.

As you can see, the differences if I didnt use the ViewModel is that the view :

  • define the fields that will be displayed itself (without using a ViewModel)
  • get the data using a query which return here an entity (but which could return something else if needed) then use it to set the variables
  • convert the variables to an entity (or another object if needed) and call a command to save the information => this seems really similar to how I would develop a desktop application

I would be interested by the pros and cons of each approach.

UPDATE @Henk Holterman : I change the GetUserQuery of the example 2 by GetUserEditViewQuery

@Ben Sampica : First, thanks for your answer. If I understand you correctly, In a use case "Change user information", the ViewModel (UserEditViewModel) will contain all information needed to edit the user. In a use case "View user information", the ViewModel (UserViewViewModel : not really nice but ...) will contain all information needed to view the user (which can differ from the change page). => the queries are different and so return different ViewModel.

I understood and it makes sense.

But is there only one ViewModel by page or can I use more than one? Indeed, in some cases, pages contains list with a button which permits the user to add an element in this list. For me, adding an element in the list will call a new query which add the element in the database then the list is refreshed.

In lot of examples, I see people create a property in the ViewModel of the page (say UserEditViewModel) and populate it in the main query (say GetUserEditViewQuery) which is not really possible here. If I had to do it, I would certainly do something like this :

this.List = await Mediator.Send(new GetListForUserEditViewQuery());
this.User = await Mediator.Send(new GetUserEditViewQuery());

Would it be correct ?

question from:https://stackoverflow.com/questions/65833599/is-there-a-reason-to-use-viewmodel-in-blazor-server-side

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Part of the framework of a vertical slice architecture is having an architecture. By coupling your domain directly to your presentation, you're opening yourself up for issues when different views need different things. Your GetUserQuery shouldn't be that at all, it should be GetUserEditViewQuery with the things the view needs - a user, a title, etc. Vertical slicing is about use cases, in such case a person needs to view all the editable information about a user.

Your query should return a ViewModel/DTO that represents the use of that view back to the view.

If you can be absolutely positive that such will never be the case - sure, go and use the User directly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...