Skip to main content
 首页 » 编程设计

c#之ASP.NET MVC 将 ListFoo> 集合从我的 View 发送到 Controller

2024年01月29日28haluo1

我在 ASP.NET 中有一个应用程序,我想将这个对象列表传递给我的 Controller。现在应用程序正在做的是通过sql 查询 填充列表,然后将所述列表加载到 View 。接下来,我根据获得的数据将列表分为 4 个颜色类别:红色、蓝色、绿色和黄色(分别)。我在 4 <divs> 上显示了他们每个人的计数.每个 div 都是它自己的 ActionLink,现在将一个字符串发送到包含颜色名称的 Controller。

Controller 然后获取该字符串并将其与查询进行比较,查询返回属于该颜色类别的列表对象;然后我对该列表做任何我想做的事。

但我的问题是,我不得不一遍又一遍地提取这些数据,而且花费的时间太长了。有没有一种方法可以让我只加载一次列表,然后将其传递给我的 Controller ,这样我就不会一直等待查询完成加载?

这是我的模型:

using System.Collections.Generic; 
 
namespace Foo.Models 
{ 
  public class FooViewModel 
  { 
    public List<Foo> FooCollection = new List<Foo>(); 
    /*Contains two properties 
      string CarName {get; set;} 
      string Color   {get; set;} 
      List<Features> Features = new List<Features>(); 
    */ 
  } 
} 

我的观点

    @model Foo.Models.FooViewModel 
    @{ 
var RedCars = Model.FooCollection.Where(c => c.Color == "Red").ToList(); 
    ... //{yellow, blue, green} 
} 
    <div id="FooCollection"> 
      <section class="no-padding-top no-padding-bottom"> 
        <div class="container-fluid"> 
          <div class="public-user-block block"> 
            <div class="row d-flex align-items-center"> 
 
              <!--Red Cars--> 
                @using (Ajax.BeginForm("../Bar/Index/Red", null, 
new AjaxOptions 
{ 
HttpMethod = "post", 
InsertionMode = InsertionMode.Replace, 
UpdateTargetId = "CarsList" 
}, new { id = "RedCarsForm" })) 
  { 
        <input type="hidden" name="Cars" value="@RedCars" /> 
          <div id="status-container" class="col-lg-3 d-flex align-items-center"> 
            <button type="submit">@RedAlerts.Count</button> 
            <strong>Red Cars</strong> 
          </div> 
 
          } 
          <!-- same structure for yellow, green, blue --!> 
      </section> 
    </div> 

我的 Controller :

public ActionResult Index() 
{ 
 
   foreach (var car in db.database.Db_GetCars()) 
   { 
      model.FooCollection.Add(new Foo() 
      { 
         CarName = car.CarName, 
         Color= car.Color 
      }); 
    } 
    return View(model); 
}   

目标 Controller :

    namespace Foo.Controllers 
    { 
      public class BarController: Controller 
      { 
        BarViewModel model = new BarViewModel(); 
 
[HttpPost, Route("/Bar/Index/{color}")] 
        public ActionResult Index(List<Foo> Cars) 
        { 
          //logic goes here 
 
          return View(model); 
        } 
      } 
    } 

我想要的输出是发送完整的 List<Foo>反对我的目标 Controller 。但是现在,当它到达 Controller 时,我得到的值计数为零 (0)。谁能看到我做错了什么?非常感谢。

请您参考如下方法:

所以你的主要问题是你试图使用一个 Action (这是一个链接,一个 anchor 标记)将一个列表传递给 Controller ​​。但是 anchor 标记是一个“获取”请求,您通常不会通过获取传递列表(是的,这是可能的,但通常不建议)。您最好为此使用表单发布。这是一个基本大纲:

<!-- red cars --> 
<form action="/bar/index/red" method="post"> 
 
    @foreach(var car in Model.Where(c => c.Color == "red")) 
    { 
        <input type="hidden" name="carnames" value="@car.CarName" /> 
    } 
    <button class="btn btn-primary" type="submit">Red Cars</button> 
 
</form> 
 
<!-- green cars --> 
<form action="/bar/index/green" method="post"> 
 
    @foreach(var car in Model.Where(c => c.Color == "green")) 
    { 
        <input type="hidden" name="carnames" value="@car.CarName" /> 
    } 
    <button class="btn btn-primary" type="submit">Green Cars</button> 
 
</form> 
 
<!-- blue cars --> 
<form action="/bar/index/blue" method="post"> 
 
    @foreach(var car in Model.Where(c => c.Color == "blue")) 
    { 
        <input type="hidden" name="carnames" value="@car.CarName" /> 
    } 
    <button class="btn btn-primary" type="submit">Blue Cars</button> 
 
</form> 
 
<!-- yeller cars --> 
<form action="/bar/index/yellow" method="post"> 
 
    @foreach(var car in Model.Where(c => c.Color == "yellow")) 
    { 
        <input type="hidden" name="carnames" value="@car.CarName" /> 
    } 
    <button class="btn btn-primary" type="submit">Yellow Cars</button> 
 
</form> 

这会为每种颜色创建一个表单,因此当您单击提交按钮时,只会发送该表单中的汽车。请注意,输入名称始终相同。这就是将它们打包在一个列表中的方式。

在你的 Controller 中,使用这样的东西:

[HttpPost, Route("bar/index/{color}")] 
public IActionResult Index(string color, List<string> carNames) 
{ 
    // do stuff... 
 
    return View(); 
} 

color变量将从 url 中获取,carNames 将从帖子中提取。

编辑: 在评论中,添加的问题基本上是“如果我想要汽车名称和对象上的颜色,所以要发布一个 List<Foo> 怎么办?

发布复杂对象的列表有点困惑,但这是您在 View 中需要的:

<!-- red cars --> 
<form action="/stuff/cars/red" method="post"> 
    @{ 
        var cars = Model.Where(c => c.Color == "red").ToList(); 
        for (var i = 0; i < cars.Count; i++) 
        { 
            <text> 
            <input type="hidden" name="cars.Index" value="@i" /> 
            <input type="hidden" name="cars[@i].CarName" value="@cars[i].CarName" /> 
            <input type="hidden" name="cars[@i].Color" value="@cars[i].Color" /> 
            </text> 
        } 
    } 
    <button class="btn btn-primary" type="submit">Red Cars</button> 
 
</form> 

切换到常规 for loop 给了我们一个索引变量,我们用它来告诉表单哪对值属于一起。另请注意,我实际上创建了一个临时文件 var cars = ...在它上面,这样我就可以遍历较小的列表。现在只需更改其他颜色以匹配此代码并更改您的 Controller 以接受 string color, List<Foo> cars一切就绪!

编辑 2: 如果您想在 ajax 中执行此操作,则在 javascript 中创建一个对象:

var cars = [ 
    { 'CarName': 'name', 'Color': 'color' }, 
    { 'CarName': 'name', 'Color': 'color' }, 
    { 'CarName': 'name', 'Color': 'color' }, 
    { 'CarName': 'name', 'Color': 'color' }, 
    { 'CarName': 'name', 'Color': 'color' } 
]; 

您可以填充实际的 name和 color使用 jQuery 的各种方式。然后使用ajax发帖:

$(document).ready(function() 
{ 
    $('#ajaxPost').click(function () 
    { 
        $.ajax( 
        { 
            type: 'POST', 
            url: '/stuff/cars', 
            contentType: "application/json", 
            data: JSON.stringify(cars), 
            success: function (data) 
            { 
                // do stuff 
            }, 
            error: function (e) 
            { 
                alert(e); 
 
            } 
 
        }); 
    }); 
}); 

注意:这将是 Controller 中与前一个端点不同的端点。根据您使用的 .net 版本,情况会略有不同。

新 Controller Action :

[HttpPost, Route("stuff/cars/")] 
public IActionResult Cars2([FromBody] List<FooViewModel> cars) 
{ 
    // do stuff... 
 
    return View(); 
} 

注意 [FromBody]标记,在 .net Core 中是必需的,JSON.stringify 也是如此。在ajax调用中。如果您不确定您使用的是哪个版本,请交替添加/删除每个版本。核心可能有点挑剔......