ASP.NET MVC发送List< Foo>从我的视图到控制器的集合
我在 ASP.NET 中有一个应用程序,我想将此对象列表传递给我的 Controller .现在,应用程序正在执行的操作是通过 sql查询填充列表,然后将该列表加载到视图.接下来,我根据获得的数据将列表分为4种颜色类别:红色,蓝色,绿色和黄色(分别).我在4 <divs>
上显示它们的计数.每个div都是其自己的 ActionLink ,现在将包含颜色名称的字符串发送到 Controller .
I have an application in ASP.NET where I want to pass this list of objects to my Controller. Right now what the application is doing is populating a list via sql query and then loads said list to the view. Up next, I divvy up the list into 4 color categories based on the data I get: red, blue, green and yellow (respectively). I display the count for each of them on 4 <divs>
. Each div is its own ActionLink and right now sends a string to a Controller containing the color name.
然后,控制器获取字符串并将其与查询进行比较,并在查询中返回属于该颜色类别的列表对象;然后我要对列表进行任何操作.
The Controller then takes the string and compares it against a query where it returns the list objects that belong to that color category; then I do whatever I want to that list.
但是我的问题是我被迫一遍又一遍地执行这些数据,并且花费的时间太长了.我有什么办法可以只加载一次列表,然后将其传递给控制器,这样我就不会停留在等待查询完成加载了?
But my issue is that I am forced to do this data pull over and over and it takes too long as is. Is there a way for me to just load up the list once then pass it to my controller so I am not stuck waiting for my query to finish loading?
这是我的模型:
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>
我的控制器:
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);
}
目标控制器:
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>
对象发送到我的目的地控制器.但是现在,当到达控制器时,我得到的值为零(0).谁能看到我做错了吗?预先非常感谢.
My desired output is to send the complete List<Foo>
object to my Destination Controller. But right now I am getting a value count of zero (0) when it gets to the controller. Can anyone see what I am doing wrong? Many thanks in advance.
因此,您的主要问题是您试图使用操作(这是一个链接,一个定位标记)将一个列表传递给控制器.但是锚标记是一个获取"请求,通常您不会通过Gets传递列表(是的,有可能,但通常不建议这样做).您最好为此使用一个表单发布.这是一个基本概述:
So your main problem is that you are trying to use an action (which is a link, an anchor tag) to pass a list to the controller. But an anchor tag is a "Get" request and you normally don't pass lists via Gets (yes, it is possible, but generally not advised). It would be better for you to use a form post for this. Here is a basic outline:
<!-- 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>
这会为每种颜色创建一个表单,因此当您单击提交"按钮时,只会在该帖子中发送该表单中的汽车.请注意,输入名称始终相同.这样便可以将它们包装在一个列表中.
This creates a form for each color so when you click the submit button, only the cars from that one form are sent in the post. Note that the input name is always the same. That is how you get them wrapped together in a list.
在您的控制器中,使用类似以下的内容:
In your controller, use something like this:
[HttpPost, Route("bar/index/{color}")]
public IActionResult Index(string color, List<string> carNames)
{
// do stuff...
return View();
}
color
变量将从网址中提取,而carNames将从帖子中提取.
The color
variable will get picked up from the url and the carNames will be pulled in from the post.
在评论中,添加的问题本质上是如果我要发布对象上的汽车名称和颜色,那么要发布List<Foo>
,该怎么办?
In the comments the added question was essentially "what if I want the car name and the color on the object, so a List<Foo>
, to be posted?
发布复杂对象列表会比较麻烦,但这是您在视图中需要的:
Posting a list of complex objects is a bit messier but here is what you need in the 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
循环将为我们提供一个索引变量,该变量用于告诉表单哪对值属于同一对.还要注意,我实际上在其上方创建了一个temp var cars = ...
,以便可以遍历较小的列表.现在只需更改其他颜色以匹配此代码,然后将控制器更改为接受string color, List<Foo> cars
就可以了!
Switching to a regular for
loop gives us an index variable which we use to tell the form which pair of values belongs together. Notice also that I actually created a temp var cars = ...
above it so that I can loop through the smaller list. Now just change the other colors to match this code and change your controller to accept string color, List<Foo> cars
and you are all set!
如果您想在ajax中执行此操作,请在javascript中创建一个对象:
Edit 2: If you want to do this in ajax instead then create an object in the javascript:
var cars = [
{ 'CarName': 'name', 'Color': 'color' },
{ 'CarName': 'name', 'Color': 'color' },
{ 'CarName': 'name', 'Color': 'color' },
{ 'CarName': 'name', 'Color': 'color' },
{ 'CarName': 'name', 'Color': 'color' }
];
您可以使用jQuery以各种方式填充实际的name
和color
.然后使用ajax发布:
You can populate the actual name
and color
various ways using jQuery. Then use ajax post:
$(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);
}
});
});
});
注意:这将是控制器中与上一个端点不同的端点.取决于您所使用的.net版本,事情的表现会略有不同.
Note: This will be a different endpoint in the controller from the previous one. Depending on which version of .net you are using things will act slightly differently.
新控制器动作:
[HttpPost, Route("stuff/cars/")]
public IActionResult Cars2([FromBody] List<FooViewModel> cars)
{
// do stuff...
return View();
}
请注意[FromBody]
标记,这是.net Core中必需的标记,就像ajax调用中的JSON.stringify
一样.如果不确定所使用的版本,请交替添加/删除每个版本.核心可能有点挑剔...
Notice the [FromBody]
tag, that is necessary in .net Core, as is the JSON.stringify
in the ajax call. If you aren't sure which version you are on, alternate adding/removing each of those. Core can be a little finicky...