【问题标题】:How to pass ViewModels into Razor Components in .NET Core 3.1如何将 ViewModel 传递到 .NET Core 3.1 中的 Razor 组件
【发布时间】:2020-04-06 01:07:44
【问题描述】:

我有一个包含以下内容的 View MyView.cshtml:

@using MyProject.ViewModels
@model MyProject.ViewModels.MyViewViewModel

<form asp-action="Test" method="Post">
    <component type="typeof(MyProject.Views.Home.Test)" render-mode="ServerPrerendered" />
    <input type="submit" value="send"/>
</form>

我有 Razor 组件 Test.razor 具有以下内容(使用 Blazor 语法):

@page "/Test"

<div class="form-group top-buffer @Visible">
    <div class="row">
        <div class="col-2">
            <label asp-for="TestName" class="control-label"></label>
        </div>
        <div class="col-3">
            <input asp-for="TestName" class="form-control" />
            <span asp-validation-for="TestName" class="text-danger"></span>
        </div>
    </div>
</div>

<button @onclick="Show">Show</button>

@code {
    public string Visible { get; set; } = "hidden";

    protected async Task Show()
    {
         Visible = "";
    }
}

MyViewViewModel 类如下所示:

namespace MyProject.ViewModels
{
    public class MyViewViewModel
    {
        [Display(Name = "Test Name:")]
        public string TestName { get; set; }
    }
}

到目前为止一切正常。但是,我现在想将此组件用作 Web 表单的一部分,该表单将在提交后发送到控制器。这就是为什么我需要访问和更改我的 ViewModel 'MyViewViewModel' 的属性。不幸的是,我在互联网上没有找到任何关于如何做到这一点的答案。我不能像在视图中那样使用@model MyProject.ViewModels.MyViewViewModel,因为这会给我一个编译错误。我想知道我是否需要使用@inject,但如果是,我不知道如何......

(此示例中使用的部分:https://jonhilton.net/use-blazor-in-existing-app/

【问题讨论】:

  • 这个剃须刀页面的 .cs 是什么样的。例如:MyViewModel 有什么作用
  • 我更新了我的帖子。现在是否清楚我将尝试实现的目标?我的意思是我想避免使用 JS 并改用 C# Blazor。我明白我必须使用组件,但我不明白如何从这样的组件中读取和写入 ViewModel 中的属性。
  • 我将尝试现场解决这个问题,并在完成后将解决方案发回此处。 twitter.com/EdCharbeneau/status/1205520278480203776

标签: asp.net-core-mvc viewmodel razor-pages blazor .net-core-3.1


【解决方案1】:

在 Razor 页面中混合 Blazor 时,可以执行以下操作:

  • 渲染 Razor 组件
  • 与 Razor 组件交互
  • 传递 Razor 组件值

请记住,您正在处理两个不同的生命周期。因此,如果您确实在 Razor 组件内部工作,该组件将更新但不会影响托管在其中的 Razor 页面。因此,将 Razor 组件和页面与表单混合起来会很困难。

更具体地说是 OP。要将数据从 ViewModel 传递到组件,您可以使用以下方法。

@using MyProject.ViewModels
@model MyProject.ViewModels.MyViewViewModel

<form asp-action="Test" method="Post">
    <component type="typeof(MyProject.Views.Home.Test)" 
               render-mode="ServerPrerendered" 
               param-Name="@Model.TestName"/>
    <input type="submit" value="send"/>
</form>

Test.razor

<h3>HelloWorld</h3>

Hello @Name

@code {

    [Parameter]
    public string Name { get; set; } = "undefined";

}

关于生命周期 基本上,当您在 Blazor 中有一个按钮时,它将触发一个导致组件重新呈现的事件。你可以把它想象成一个 iframe 或更新面板。当您在 Razor 页面中有一个按钮时,它会执行 HTTP 调用往返并完全重新加载页面。没有适当的事件系统来告诉 Blazor 调用 HTTP 调用往返以刷新 Razor 页面的内容,反之亦然。您只能从 Razor 页面到 Blazor 的单向数据绑定,认为只写,并且仅在页面加载时。

【讨论】:

  • 非常感谢您为它付出了这么多努力,我非常感谢它,顺便说一句,刚刚在 twitch 上关注了您。但是,您表示在使用表单时混合这些东西是一个问题......您能否解释更多关于生命周期的信息或为我提供链接?另外,有没有更好的方法,如何解决?我真的不是 Javascript 的粉丝,我想用 Blazor 替换它。但如果还没有任何“直截了当”的方式,我可能还是会选择 JS。
  • 抱歉,没有什么可以链接到您,因为这是未知领域。更新了答案以展开。
  • 集成这两种技术的最佳方式是在同一个项目中使用它们,但不要在一个页面中混合使用它们。如果您打算在页面上使用 Blazor(又名 Razor 组件),请仅使用 Razor Pages 路由到该页面,并使整个页面成为一个组件。
【解决方案2】:

希望添加到信息中。使用 ASP.Net Core MVC 项目托管 Blazor webassembly,我试图在我的视图 cshtml 文件中使用以下代码将视图模型传递到剃须刀组件: &lt;component Type="typeof(Leave)" render-mode="WebAssembly" model="new { model = (MyViewModel)@Model})"/&gt;

但是,如果我尝试从 razor 组件访问 viewmodel 中的数据且对象未设置异常,它将无法呈现 razor 组件。我认为它是在视图模型初始化之前访问数据。也许如果我设置一个可以避免的默认值?

我发现通过使用它,我能够让它工作。

@(await Html.RenderComponentAsync&lt;Leave&gt;(RenderMode.WebAssembly,new { model = (MyViewModel)@Model}))

编辑 看来您还需要在 Program.cs 文件的 Blazor WASM 项目的服务中注册 viewModel 类。

builder.Services.AddScoped(sp => new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<MyViewModel,MyViewModel>();   // <= add this line

await builder.Build().RunAsync();`

否则,我会收到一条错误消息,指出无法找到该属性。

希望这可以为其他人节省一些时间:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 2016-07-18
    • 1970-01-01
    • 2021-09-25
    • 2021-02-04
    • 2020-04-02
    相关资源
    最近更新 更多