本文介绍了.NET Core MVC - 带有前缀绑定的 AJAX POST 请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想通过 AJAX 向带有模型前缀的控制器发布请求.我需要一个前缀,因为我在一个页面上有两个具有相似模型属性的表单(asp-for"正在生成相似的 ID 和名称).我使用的是 .NET Core 3.1.
请求帖子无需前缀即可正常工作.当我在下面的例子中使用前缀时,传递的模型在控制器中为空:
带前缀的控制器
[HttpPost]公共异步任务Save([Bind(Prefix="ShipmentAddress"), FromBody]ShipToAddressViewModel 模型){//模型为空...返回 PartialView(ShipmentAdressFormView, 模型);}
查看前缀
在我的视图中,我也设置了 HTMLFieldPrefix:
@model ShipToAddressViewModel@{ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "ShipmentAddress";}...$("body").on('submit','#formShipmentAddress', function (e) {//获取数据(参见下面传递的 JSON)var formData = new FormData(document.getElementById('formShipmentAddress'));var 对象 = {};formData.forEach(function (value, key) {对象[键] = 值;});var 数据 = 对象;$.ajax({类型:POST",网址:网址,数据:JSON.stringify(数据),contentType: "application/json; charset=utf-8",成功:(数据)=>{成功(数据);}});});
传递带前缀的 JSON 负载
{"ShipmentAddress.ID":"3","ShipmentAddress.Name":"Eddard Stark","ShipmentAddress.Name2":"c/o Ned",..."}
型号
公共类 ShipToAddressViewModel{公共 int ID { 获取;放;}[显示(名称=名称")]公共字符串名称 { 获取;放;}[显示(名称=名称2")]公共字符串 Name2 { 获取;放;}...}
更新
如果我从我的对象的键中删除前缀,那么它就可以工作,尽管更像是一种解决方法(模型绑定从查看键 ShipmentAddress.ID 的源开始.如果没有找到,它会寻找不带前缀的 ID.):
//获取数据(见下面传递的 JSON)var formData = new FormData(document.getElementById('formShipmentAddress'));var 对象 = {};formData.forEach(function (value, key) {object[key.replace("ShipmentAddress.","")] = value;});var 数据 = 对象;
解决方案
对于 Asp.Net Core,有两种绑定模型的方式,ModelBinding
和 JsonInputFormatter
.对于使用 json 发送请求,它将使用 JsonInputFormatter
.Bind
不适用于 JsonInputFormatter
.
这是一个如下所示的工作演示:
1.查看:
@{ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "ShipmentAddress";}@model ShipToAddressViewModel<form id="formShipmentAddress"><div asp-validation-summary="ModelOnly" class="text-danger"></div><div class="form-group"><label asp-for="ID" class="control-label"></label><input class="form-control" asp-for="ID"><span asp-validation-for="ID" class="text-danger"></span>
<div class="form-group"><label asp-for="Name" class="control-label"></label><input class="form-control" asp-for="Name"><span asp-validation-for="Name" class="text-danger"></span>
<div class="form-group"><label asp-for="Name2" class="control-label"></label><input class="form-control" asp-for="Name2"><span asp-validation-for="Name2" class="text-danger"></span>
<div class="form-group"><input type="submit" value="Create" class="btn btn-primary"/>
</表单>@section 脚本{<脚本>$("body").on('submit', '#formShipmentAddress', function (e) {e.preventDefault();var id = parseInt($("#ShipmentAddress_ID").val());var name = $("#ShipmentAddress_Name").val();var name2 = $("#ShipmentAddress_Name2").val();变量数据 = {身份证:身份证,姓名:姓名,姓名 2:姓名 2};$.ajax({类型:POST",url: "/首页/保存",数据:JSON.stringify(数据),contentType: "application/json; charset=utf-8",成功:(数据)=>{成功(数据);}});});}
2.控制器:
public async Task保存([FromBody]ShipToAddressViewModel 模型){//做你的事...}
3.结果:
I would like to post a request via AJAX to a Controller with a model prefix. I need a prefix as I have two forms on one page with similiar model properties ("asp-for" is generating similiar IDs and Names). I'm using .NET Core 3.1.
Request post works fine without a prefix. When I'm using a prefix like in the example below, passed model is null in Controller:
Controller with prefix
[HttpPost]
public async Task<IActionResult> Save([Bind(Prefix="ShipmentAddress"), FromBody]ShipToAddressViewModel model)
{
// model is null
...
return PartialView(ShipmentAdressFormView, model);
}
View with prefix
In my View I set the HTMLFieldPrefix as well:
@model ShipToAddressViewModel
@{
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "ShipmentAddress";
}
...
$("body").on('submit','#formShipmentAddress', function (e) {
// Getting the data (see passed JSON below)
var formData = new FormData(<HTMLFormElement>document.getElementById('formShipmentAddress'));
var object = {};
formData.forEach(function (value, key) {
object[key] = value;
});
var data = object;
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: (data) => {
success(data);
}
});
});
Passed JSON payload with prefix
{"ShipmentAddress.ID":"3","ShipmentAddress.Name":"Eddard Stark","ShipmentAddress.Name2":"c/o Ned",..."}
Model
public class ShipToAddressViewModel
{
public int ID { get; set; }
[Display(Name="Name")]
public string Name { get; set; }
[Display(Name = "Name 2")]
public string Name2 { get; set; }
...
}
UPDATE
If I remove the prefix from keys of my objects, then it works, though more like a work around (Model binding starts by looking through the sources for the key ShipmentAddress.ID. If that isn't found, it looks for ID without a prefix.):
// Getting the data (see passed JSON below)
var formData = new FormData(<HTMLFormElement>document.getElementById('formShipmentAddress'));
var object = {};
formData.forEach(function (value, key) {
object[key.replace("ShipmentAddress.","")] = value;
});
var data = object;
解决方案
For Asp.Net Core, there are two ways to bind the model, ModelBinding
and JsonInputFormatter
. For sending request with json, it will use JsonInputFormatter
. Bind
will not work with JsonInputFormatter
.
Here is a working demo like below:
1.View:
@{
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "ShipmentAddress";
}
@model ShipToAddressViewModel
<form id="formShipmentAddress">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ID" class="control-label"></label>
<input class="form-control" asp-for="ID">
<span asp-validation-for="ID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input class="form-control" asp-for="Name">
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name2" class="control-label"></label>
<input class="form-control" asp-for="Name2">
<span asp-validation-for="Name2" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
@section Scripts
{
<script>
$("body").on('submit', '#formShipmentAddress', function (e) {
e.preventDefault();
var id = parseInt($("#ShipmentAddress_ID").val());
var name = $("#ShipmentAddress_Name").val();
var name2 = $("#ShipmentAddress_Name2").val();
var data = {
ID: id,
Name: name,
Name2: name2
};
$.ajax({
type: "POST",
url: "/Home/Save",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: (data) => {
success(data);
}
});
});
</script>
}
2.Controller:
public async Task<IActionResult> Save([FromBody]ShipToAddressViewModel model)
{
//do your stuff...
}
3.Result:
这篇关于.NET Core MVC - 带有前缀绑定的 AJAX POST 请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!