【问题标题】:How can I reuse a contact form in a ViewComponent?如何在 ViewComponent 中重用联系表单?
【发布时间】:2021-03-15 06:28:59
【问题描述】:

我想在我的项目的多个页面上使用相同的联系表单。

我在一个名为 FormInViewComponent 的示例项目上进行了尝试,如下所示:

Controllers > TestController.cs

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
    
namespace FormInViewComponent.Controllers
{
    public class TestController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Views > Test > Index.cshtml(我在这个页面上调用了ViewComponent)

@model FormModel
<div class="container">
    <div class="row">
        <div class="col-8">
            <h3>Page content is here</h3>
        </div>
        <div class="col-4 bg-light p-3">
            @await Component.InvokeAsync("SampleForm")
        </div>
    </div>
</div>

Models > FormModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
    
namespace FormInViewComponent.Models
{
    public class FormModel
    {
        [Required]
        public string Name { get; set; }
    }
}

ViewComponents > SampleFormViewComponent.cs

using FormInViewComponent.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
    
namespace FormInViewComponent.ViewComponents
{
    public class SampleFormViewComponent : ViewComponent
    {
        public async Task<IViewComponentResult> InvokeAsync(FormModel formModel)
        {
            return await Task.FromResult(View(formModel));
        }
    }
}

Views > Shared > Components > SampleForm > Default.cshtml

@model FormModel
    
<h4>ViewComponent is here</h4>
<b class="text-info">Sample Form</b>
<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="col-12">
        <div class="form-group">
            <label asp-for="Name"></label><br />
            <input type="text" asp-for="Name" class="form-control" />
            <span asp-validation-for="Name" class="text-danger"></span>
        </div>
        <p class="text-center">
            <input class="btn btn-success" type="submit" value="Send" />
        </p>
    </div>
</form>

【问题讨论】:

  • 除此之外,您能否编辑您的问题以包括对什么不起作用的解释?例如,您是否遇到了异常——如果是,那是什么?根据您的代码,我的假设是您没有收到错误,而且您的表单没有呈现,因为 Component.InvokeAsync() 的问题往往会默默地失败。如果是这样,这将有助于受访者知道。同时,我根据我期望通过您的代码阅读的内容提供了一个答案。

标签: asp.net-core asp.net-core-3.1 asp.net-core-viewcomponent view-components


【解决方案1】:

最直接的问题是您尝试在没有任何参数的情况下调用 SampleFormViewComponent,但您的 InvokeAsync() 方法需要 FormModel 参数。因此,虽然它可能能够找到您的SampleFormViewComponent,但它无法执行InvokeAsync()。

将FormModel 作为参数传递

要解决这个问题,您必须使用以下语法将FormModel 的实例传递给您的Component.InvokeAsync() 调用:

@await Component.InvokeAsync("SampleForm", new { formModel = new FormModel() })

内联构造FormModel

根据您的确切要求,替代方法是删除 formModel 参数,而是在您的 InvokeAsync() 方法中构建您的视图组件:

namespace FormInViewComponent.ViewComponents
{
    public class SampleFormViewComponent : ViewComponent
    {
        public async Task<IViewComponentResult> InvokeAsync()
        {
            var formModel = new FormModel();
            return await Task.FromResult(View(formModel));
        }
    }
}

显然,视图模型通常会有与之关联的数据。您可以从当前上下文(例如,从路由参数或查询字符串)中提取该数据,或使用该信息从另一个位置(例如数据库)查找数据。

处理您的表单

然而,这引发了另一个问题:您希望如何处理您的表单?如果您将其发布到单独的控制器操作或例如网络服务,没问题。如果您希望视图组件也处理结果,就像在控制器中一样,那么您将遇到困难。值得注意的是,视图组件不提供任何类型的路由或复杂的模型绑定。因此,虽然您可以使用视图组件呈现表单,但您应该使用控制器或 Web 服务处理表单。

【讨论】:

  • 艾哈迈德,你还记得这是否回答了你的问题吗?如果是这样,您能否确保将其标记为已接受的答案?这会将这个问题标记为已解决——并有助于提升我自己的声誉:)
猜你喜欢
  • 2015-09-18
  • 2021-04-16
  • 1970-01-01
  • 2012-09-10
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多