1

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

我在一个名为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>
4

1 回答 1

0

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

FormModel作为参数传递

要解决此问题,您必须使用以下语法将 a 的实例传递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 服务,那没问题。如果您希望您的视图组件处理结果,就像您在控制器中一样,您将遇到困难。值得注意的是,视图组件不提供任何类型的路由或复杂的模型绑定。因此,虽然您可以使用视图组件呈现表单,但您应该使用控制器或 Web 服务来处理表单。

于 2020-12-24T22:31:55.820 回答