.NET Core MVC - 带有前缀绑定的 AJAX POST 请求

Posted

技术标签:

【中文标题】.NET Core MVC - 带有前缀绑定的 AJAX POST 请求【英文标题】:.NET Core MVC - AJAX POST Request with prefix binding 【发布时间】:2020-05-26 14:52:05 【问题描述】:

我想通过 AJAX 将请求发布到带有模型前缀的控制器。我需要一个前缀,因为我在一个页面上有两个具有类似模型属性的表单(“asp-for”正在生成类似的 ID 和名称)。我正在使用 .NET Core 3.1。

请求帖子无需前缀即可正常工作。当我使用下面示例中的前缀时,控制器中传递的模型为空:

带前缀的控制器

    [HttpPost]
    public async Task<IActionResult> Save([Bind(Prefix="ShipmentAddress"), FromBody]ShipToAddressViewModel model)
    
        // model is null
        ...
        return PartialView(ShipmentAdressFormView, model);
    

带前缀查看

在我的视图中,我也设置了 htmlFieldPrefix:

@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);
        
    );
);

传递带有前缀的 JSON 负载

"ShipmentAddress.ID":"3","ShipmentAddress.Name":"Eddard Stark","ShipmentAddress.Name2":"c/o Ned",..."

型号

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; 
    ...

更新

如果我从对象的键中删除前缀,那么它就可以工作,尽管更像是一种变通方法(模型绑定首先查看键 ShipmentAddress.ID 的源。如果找不到,它会寻找没有前缀的ID。):

    // 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;

【问题讨论】:

艾德·史塔克 :'( 我通过遍历表单数据来获取数据,当我将前缀替换为“nothing”时,即使在您的示例中也可以使用。数据类型没有影响,.NET 无论如何都可以解析它。 【参考方案1】:

对于Asp.Net Core,绑定模型有两种方式,ModelBindingJsonInputFormatter。对于使用 json 发送请求,它将使用 JsonInputFormatterBind 不适用于 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>
    <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.控制器:

public async Task<IActionResult> Save([FromBody]ShipToAddressViewModel model)

    //do your stuff...

3.结果:

【讨论】:

嗨,感谢您的详细说明和说明性回答,但存在一些混淆:在您的示例中,您传递了以下 json:"ID":3,"Name":"Eddard Stark".., 而不是 "ShipmentAddress.ID":3,"Name":"ShipmentAddress.Eddard Stark"..,。这就是它起作用的原因。 .NET Core 有一个后备方案:模型绑定首先查看关键 AddressShipoment.ID 的源。如果没有找到,它会查找不带前缀的 ID。所以我在发回之前手动删除了 javascript 中的前缀,然后它就可以工作了。虽然它实际上更多的是一种解决方法。你知道我的意思吗? 是的,我知道你的意思。我无法通过使用你的代码获得像你这样的带后缀的 json。你能分享你如何获取数据吗?你是否尝试将 ShipToAddressViewModel model 更改为 @ 987654333@在你的行动? 对于Asp.Net Core,绑定模型有两种方式,ModelBindingJsonInputFormatter。对于使用 json 发送请求,它将使用JsonInputFormatter Bind 不能与 JsonInputFormatter 一起使用。 @rena,请将您的最后一条评论添加到您当前答案的顶部,它完美地回答了这个问题,将它放在那里对有同样问题的人会非常有帮助 嗨@jalsh。好的,我做到了。

以上是关于.NET Core MVC - 带有前缀绑定的 AJAX POST 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Asp.Net Core 中为日期绑定设置文化?

ASP.NET Core MVC 混合路由/FromBody 模型绑定和验证

带有实体框架的 ASP.NET MVC Core 项目中的种子角色

在 ASP.NET MVC Core 2 中使用 MetadataPropertyHandling 模型绑定 JSON 数据

NET Core 3.1 MVC 授权/身份验证,带有在单独的 Net Core 3.1 Web Api 中从外部获取的令牌 (JWT)

IFormFile 始终为空(带有 MVC/Razor 的 ASP.NET Core)