You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从ASP.NET自定义TagHelper中获取表单提交数据?

自定义TagHelper循环渲染问卷问题,POST提交无法绑定模型数据

我做了一个带问答的问卷,在编辑视图里用自定义TagHelper循环展示各章节和对应的问题。提交表单POST请求时,想获取所有问题的修改数据并存到数据库。一般用asp-for属性就能绑定输入,但我加了ModelExpression还是拿不到数据。相关代码如下:


问卷视图

<form asp-controller="Response" asp-action="Edit" method="post">
    @foreach (Section section in Model.Survey.Metadata.Sections.OrderBy(e => e.Position))
    {
        <div class="card" id="a@(section.Id.Replace("-", ""))">
            <div class="card-body">
                <h1>@(section.Title)</h1>
                @if (!string.IsNullOrEmpty(section.Description))
                {
                    <div>
                        @Html.Raw(section.Description)
                    </div>
                }
                <hr />
                @foreach (QuestionMetadata question in Model.Survey.Questions.Where(e => e.SectionId == section.Id).OrderBy(e => e.Position))
                {
                    <script>
                        @(ViewData["id"])SetValue[@Html.Raw($"\"a{question.Id.ToString().Replace("-", "").Split(":")[1]}\"")] = function (value, modified = true) {
                            $("#@($"{ViewData["id"]}-{question.Id.ToString().Replace("-", "").Split(":")[1]}-value")").val(JSON.stringify(
                                {
                                    Value: value,
                                    QuestionId: "@question.Id",
                                    Modified: modified
                                }
                            ));
                        };
                        @(ViewData["id"])GetValue[@Html.Raw($"\"a{question.Id.ToString().Replace("-", "").Split(":")[1]}\"")] = function () {
                            return JSON.parse(
                                $("#@($"{ViewData["id"]}-{question.Id.ToString().Replace("-", "").Split(":")[1]}-value")").val())
                                .Value;
                        };
                    </script>
                    <question survey="@Model.Survey.Metadata" answers="@Model.Survey.Metadata.Answers.ToArray()" survey-id="@ViewData["id"]" question=@question answer="@Model.Survey.Metadata.Answers.First(e => e.QuestionId == question.Id)" site-id="@Model.Survey.Metadata.SiteId" />
                    <hr />
                }
            </div>
        </div>
    }
    <div class="card">
        <div class="card-body">
                <button type="submit" asp-route-SurveyId="@Model.Survey.Metadata.Id" class=" @($"{ViewData["id"]}-button-{Model.Survey.Metadata.Id.Replace(":", "")}-survey-js")
                button-anchor">
                Submit
            </button>
        </div>
    </div>
</form>

Question标签助手

using ApplicationCore.Entities;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Threading.Tasks;
using Web.Models;

namespace Web.TagHelpers
{
    // You may need to install the Microsoft.AspNetCore.Razor.Runtime package into your project
    [HtmlTargetElement("question")]
    public class QuestionTagHelper : BaseTagHelper
    {
        [HtmlAttributeName("asp-for")]
        public ModelExpression AspFor { get; set; }
        public QuestionMetadata Question { get; set; }
        public Answer Answer { get; set; }
        public string SurveyId { get; set; } = Guid.NewGuid().ToString();
        public string SiteId { get; set; }
        public SurveyMetadata Survey { get; set; }
        public Answer[] Answers { get; set; }

        public QuestionTagHelper(ICompositeViewEngine viewEngine,
            IViewBufferScope viewBufferScope) : base(viewEngine, viewBufferScope)
        {
        }

        public override async Task RunAsync(TagHelperContext context, TagHelperOutput output)
        {
            string name = this.AspFor.Name;

            if (!string.IsNullOrEmpty(name))
            {
                output.Attributes.Add("name", name);    
            }

            ViewContext.ViewData["survey-id"] = SurveyId;
            Model = new QuestionTagHelperModel()
            {
                Question = Question,
                Answer = Answer,
                Required = Question.IsRequired
                    .Invoke(new()
                    {
                        { "Survey", Survey },
                        { "Answers", Answers }
                    }),
                SiteId = SiteId,
                Year = Survey.Year
            };

            output.TagMode = TagMode.StartTagAndEndTag;
        }
    }
}

Action方法

[HttpPost]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> Edit(Edit.Command command)
{
    if (!ModelState.IsValid)
    {
        return RedirectToAction("Index");
    }

    Edit.CommandResponse response = await _mediator.Send(command);

    if (response.NotFound)
    {
        return RedirectToAction("Index");
    }
    else
    {
        return View(response);
    }
}

模型

public class Command : IRequest<CommandResponse>
{
    [Required]
    [HiddenInput]
    public string Id { get; set; }
    public ApplicationCore.Entities.Survey Survey { get; set; }
    public List<QuestionTagHelperModel> Questions { get; set; }
    public string SurveyId { get; set; }
}

内容的提问来源于stack exchange,提问作者Nooty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:07:18