在 2 个控制器 ASP.NET Core 3.1 MVC 之间传递 ID

Posted

技术标签:

【中文标题】在 2 个控制器 ASP.NET Core 3.1 MVC 之间传递 ID【英文标题】:Pass ID between 2 controllers ASP.NET Core 3.1 MVC 【发布时间】:2021-10-04 21:37:24 【问题描述】:

我是编程新手,需要您的帮助。我正在尝试创建一个简单的测试应用程序(ASP.NET Core 3.1 MVC + EF)。我创建了 2 个模型(事件、注册)。目标是通过单击Events/Index 页面中的“注册”按钮打开带有选定EventId 的注册创建表单页面。我应该如何将EventId 传递给EnrollmentsController?我尝试使用带有隐藏输入的表单在Events/Index 页面中传递EventId,但我仍然不知道如何在EnrollmentsController 中正确处理EventId

注意:我不想在EnrollmentCreate 方法和视图中使用SelectList

如果有任何帮助,我将不胜感激。谢谢!

更新:感谢@PanagiotisKanavos,我终于在 URL 中获得了 EventId,但它仍然没有输入到表单输入中。有“0”。有什么问题?

型号
public class Event
  
    public int EventId  get; set; 

    public string Name  get; set; 

    [DataType(DataType.Date)]
    public DateTime Date  get; set; 
  

public class Enrollment
  
    public int EnrollmentId  get; set; 

    public int EventId  get; set; 
    public Event Event  get; set; 

    [Display(Name ="First name")]
    public string FirstName  get; set; 

    [Display(Name = "Last name")]
    public string LastName  get; set; 

    [Display(Name ="Enrollment date")]
    [DataType(DataType.DateTime)]
    public DateTime EnrollmentDate  get; set; 
  
Events/Index查看
    @model IEnumerable<FormTest.Models.Event>

@
  ViewData["Title"] = "Index";


<h1>Index</h1>

<p>
  <a asp-action="Create">Create New</a>
</p>
<table class="table">
  <thead>
    <tr>
      <th>
        @html.DisplayNameFor(model => model.Name)
      </th>
      <th>
        @Html.DisplayNameFor(model => model.Date)
      </th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    @foreach (var item in Model)
    
      <tr>
        <td>
          @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
          @Html.DisplayFor(modelItem => item.Date)
        </td>
        <td>
          <a asp-action="Create" asp-controller="Enrollments" asp-route-id="@item.EventId" class="btn btn-primary">Enroll</a>
        </td>
      </tr>
    
  </tbody>
</table>
Enrollments/Create查看
@model FormTest.Models.Enrollment

@
  ViewData["Title"] = "Create";


<h1>Create</h1>

<h4>Enrollment</h4>
<hr />
<div class="row">
  <div class="col-md-4">
    <form asp-action="Create">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="EventId" class="control-label"></label>
        <input class="form-control" asp-for="EventId" name="EventId" />
      </div>
      <div class="form-group">
        <label asp-for="FirstName" class="control-label"></label>
        <input asp-for="FirstName" class="form-control" />
        <span asp-validation-for="FirstName" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="LastName" class="control-label"></label>
        <input asp-for="LastName" class="form-control" />
        <span asp-validation-for="LastName" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="EnrollmentDate" class="control-label"></label>
        <input asp-for="EnrollmentDate" class="form-control" />
        <span asp-validation-for="EnrollmentDate" class="text-danger"></span>
      </div>
      <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
      </div>
    </form>
  </div>
</div>
EnrollmentsController创建方法
// GET: Enrollments/Create
    public IActionResult Create(int eventId)
    
      var newEnrollment = new Enrollment
      
        EventId = eventId,
        FirstName = "John",
        LastName = "Doe",
        EnrollmentDate = DateTime.UtcNow
      ;

      return View(newEnrollment);
    

这是屏幕:

【问题讨论】:

控制器代码在哪里?您是否有特定问题,或者您是否在询问控制器的一般工作方式?你试过ASP.NET Core MVC tutorial吗? Controllers and Views 部分准确显示您的要求。 &lt;a asp-action="Edit" asp-route-id="@item.ID"&gt;Edit&lt;/a&gt; 生成一个以 ID 作为参数调用 Edit 的链接。您可以使用样式使链接看起来像一个按钮。你可以在asp-action中传递不同的动作名称 您的意思是要将隐藏输入的值传递给操作? 如果你真的需要POST,你可以在链接按钮的onclick处理程序中使用fetch。如果你真的想要一个表格,你可以使用Form tag helpers。例如,asp-route-id="1234" 会将1234 传递给id参数 您的隐藏输入缺少name 属性:&lt;input type="hidden" value="@Html.DisplayFor(modelItem =&gt; item.EventId)" /&gt;。浏览器会忽略没有名字的输入 嗨,@Cyber​​Ant,尝试检查我更新的答案,您在asp-route-value 中的值名称与操作Create 的参数名称不一致。 【参考方案1】:

最简单的选择是使用表单,而是使用 Enrollments 控制器的链接。毕竟,目标是打开Enrollments页面,而不是提交注册:

<td>
 <a asp-controller="Enrollments" 
    asp-action="Create"
    asp-route-id="@item.EventID">Enroll</a>
</td>

可以使链接看起来像一个具有正确引导样式的按钮:

<a asp-controller="Enrollments" 
   asp-action="Create"
   asp-route-id="@item.EventID"
   class="btn btn-primary" role="button" >
Enroll
</a>

Controller 动作需要接受id 作为参数:

public IActionResult Create(int eventId)

    var newEnrollment=new Enrollment 
        EventId=eventId,
        ...
    ;
    return View(newEnrollment);

可以使用相同的路由标签助手in a form:

<td>
    <form asp-controller="Enrollments" 
          asp-action="Create"
          asp-route-id="@item.EventID" method="post">
        <button type="submit" value="Enroll"></button>
    </form>
</td>

不过,使用这样的表格有点奇怪。这需要添加一个响应POSTIndex(id) 操作以及响应GETIndex(id)

ASP.NET Core MVC Tutorial 展示了如何创建一个列出 Todo 项目的应用程序,允许编辑、删除和从列表重定向到编辑页面。

Tag Helpers in Forms 页面解释了如何使用标签助手(如 asp-controllerasp-actionasp-route-*)在表单中指定控制器、操作和参数。

【讨论】:

问题中提到控制器动作被称为Create。因此,可能需要asp-action="Create" 路由到它。 @AmalK 谢谢,我没注意到。我添加了动作 @PanagiotisKanavos 非常感谢,这很有帮助。我从来没有想过我可以像这样将 ID 传递给另一个控制器。现在我将 EventId 获取到 URL -/enrollments/create/1,这是正确的,但我仍然无法将值输入到注册/创建视图中的表单输入中。有什么建议吗? @Cyber​​Ant Create 视图是什么样的?新的注册对象将是表单的Model。您可以使用&lt;input asp-for="FirstName" class="form-control" /&gt; 显示和编辑FirstName 属性的内容。&lt;input type="hidden" asp-for="Id" /&gt; 为ID。检查 ASP.NET 教程。你可以找到代码here @PanagiotisKanavos,我更新了这个问题。请检查一下。我真的不明白怎么了...谢谢【参考方案2】:

如果你想使用asp-route-value,你需要确保值名称与动作中的参数名称一致。例如,你使用

public IActionResult Create(int eventId)

这样你就需要使用

 asp-route-eventId="@item.EventId"

【讨论】:

以上是关于在 2 个控制器 ASP.NET Core 3.1 MVC 之间传递 ID的主要内容,如果未能解决你的问题,请参考以下文章

Wcf 服务在 .NET Core 3.1 控制台应用程序中工作,但在 ASP.NET Core 3.1 Web API 中无法工作

Asp.net Core 3.1-如何从控制器返回到 Razor 页面?

Asp.Net Core 3.1 控制器方法未调用

ASP.Net Core 3.1 - 从控制器向部分视图模态传递值?

如何使用 C# 在 ASP.NET Core 3.1 MVC 中使用会话变量

ASP.NET Core 3.1 中的证书身份验证实现