是否有理由在 Blazor 服务器端使用 ViewModel?

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

我开始开发 Blazor 服务器端应用程序,我的想法是使用:

我的文件夹结构如下所示:

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

我的问题如下:在这种架构中,是否有充分的理由使用 ViewModel(如 asp .net MVC 项目)而不是直接在视图中使用实体? 下面的代码是我在不使用 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();
    }
}

使用 GetUserEditViewQuery return使用获取或延迟加载所需的所有信息创建实体。

下面的代码是我使用 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();
    }
}

使用 GetUserEditViewQuery return创建包含所有所需信息的 ViewModel。

如您所见,如果我不使用 ViewModel,不同之处在于视图 :

我会对每种方法的优缺点感兴趣。

更新 @Henk Holterman:我将示例 2 的 GetUserQuery 更改为 GetUserEditViewQuery

@Ben Sampica:首先,感谢您的回答。 如果我理解正确的话, 在“更改用户信息”用例中,ViewModel (UserEditViewModel) 将包含编辑用户所需的所有信息。 在“查看用户信息”用例中,ViewModel(UserViewViewModel:不是很好但是......)将包含查看用户所需的所有信息(可能与更改页面不同)。 => 查询不同,因此 return 不同的 ViewModel。

我明白了,很有道理。

但是页面只有一个 ViewModel 还是我可以使用多个? 实际上,在某些情况下,页面包含带有按钮的列表,允许用户在此列表中添加元素。 对我来说,在列表中添加一个元素将调用一个新查询,该查询将元素添加到数据库中,然后刷新列表。

在很多示例中,我看到人们在页面的 ViewModel(比如 UserEditViewModel)中创建了一个 属性 并将其填充到主查询(比如 GetUserEditViewQuery)中,这在这里实际上是不可能的。 如果我必须这样做,我肯定会这样做:

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

是否正确?

垂直切片架构的部分框架是具有架构。通过将您的域直接耦合到您的演示文稿,当不同的视图需要不同的东西时,您就会面临问题。您的 GetUserQuery 根本不应该是那样,它应该是 GetUserEditViewQuery 视图需要的东西 - 用户、标题等。垂直切片是关于 用例 , 在这种情况下,一个人需要查看有关用户的所有可编辑信息。

您的查询应该 return 一个 ViewModel/DTO 表示使用该视图返回视图。

如果您可以绝对肯定永远不会出现这种情况 - 当然,请直接使用用户。