本文介绍了.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,有两种绑定模型的方式,ModelBindingJsonInputFormatter.对于使用 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 请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 17:55