【问题标题】:ASP.Net Core 3.1: Controller method always recieves NULL parameter from HttpPost callASP.Net Core 3.1:控制器方法总是从 HttpPost 调用中接收 NULL 参数
【发布时间】:2019-12-13 17:09:05
【问题描述】:

我使用带有 MVC 模式的 ASP.Net Core 3.1 创建了一个全新的 Visual Studio 2019 Web 应用程序。

我的控制器有一个 HttpPost 方法,它应该有一个传入的 Json 对象(我使用 [FromBody] 作为传入参数)。

无论我尝试什么,传入的参数始终为 Null。我尝试将参数更改为字符串,并将 Model 修改为简单的 3 字段类,但它仍然以 null 的形式出现。

我使用 Chrome 的开发者工具来确保我的页面从 JavaScript Post 回调中正确发送 Json 对象(并且也使用 Postman 来做同样的事情),结果相同:我的参数仍然是 Null。

我需要做什么才能让参数作为实际值输入?

我的控制器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

using canvasApiLib.API;
using CanvasGrades.Models.AuxiliaryModels;

namespace CanvasGrades.Controllers
{
    public class FinalGradeController : Controller
    {

        public async Task<IActionResult> Index()
        {
            // Course Name
            dynamic courseDetails = await clsCoursesApi.getCourseDetails(accessToken, apiUrl, canvasCourseId);
            ViewData["CourseName"] = courseDetails.name;

            // Course Term
            dynamic courseTerm = await clsEnrollmentTermsApi.getEnrollmentTerm(accessToken, apiUrl, canvasAccountID, termNum);
            ViewData["CourseTerm"] = courseTerm.name;

            return View();
        }

        [HttpPost]
        public async Task<IActionResult> LoadTable([FromBody]DTParameters dtParameters)
        {
            //DTParameters dtParameters = new DTParameters();

            if (dtParameters == null)
            {
                dtParameters = new DTParameters();
            }
        }
    }
}

我的 DTParameters 模型:

public class DTParameters
{
    public int Draw { get; set; }
    public DTColumn[] Columns { get; set; }
    public DTOrder[] Order { get; set; }
    public int Start { get; set; }
    public int Length { get; set; }
    public DTSearch Search { get; set; }
    public IEnumerable<string> AdditionalValues { get; set; }
}

我看到的大多数示例都说明在 Startup.cs 文件的 Configure 调用中调整 app.UseMVC 实例化,但我的没有:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();
    services.AddControllersWithViews();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

(添加)

{"draw":1,"columns":[{"data":"studentName","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"studentEMail","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":null,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"finalGrade","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"lastAttendDate","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":null,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":null,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"bannerID","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"crn","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}}],"order":[{"column":0,"dir":"asc"}],"start":0,"length":10,"search":{"value":"","regex":false}}

我再次重试了我的简单参数,注意到我发送的原始 ID 字段是一个整数,但是当我将其设为字符串时(如模型所述),它没有问题。

public class SimpleParam
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Foo { get; set; }
}

{"id": "1", "name": "fred", "foo": "bob"}

所以,这意味着我必须弄清楚我的 DTParameters 模型出了什么问题。

【问题讨论】:

  • 您能否分享发送到 API 的 JSON 正文?
  • 所以,原来我的问题出在原始 JSON 上。有没有更好的方法来调试/诊断这些问题?更健壮的解析方法怎么样?
  • 创建一个 DTParameters 对象并用数据填充它,使用 JsonConvert.SerializeObject 对其进行序列化,对其进行调试并复制字符串,然后将该字符串用作 api 的输入。
  • 或将所有类复制粘贴到csharp2json.io 以获得正确的输入。
  • 请尝试在配置服务方法中添加 newtonsoft json,它可能会起作用(在我的情况下是问题)

标签: c# asp.net-core-3.1


【解决方案1】:

错误是“dir”:“asc”。您需要将其更改为 int ("dir": 0),或者使用

装饰类属性或枚举
[JsonConverter(typeof(JsonStringEnumConverter))]

或者把它放在startup.cs中

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddControllers()
        .AddJsonOptions(options => 
           options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
        );

    //...
 }

你的输入被美化了:

{
    "draw": 1,
    "columns": [
        {
            "data": "studentName",
            "name": "",
            "searchable": true,
            "orderable": true,
            "search": {
                "value": "",
                "regex": false
            }
        }
    ],
    "order": [
        {
            "column": 0,
            "dir": "asc"
        }
    ],
    "start": 0,
    "length": 10,
    "search": {
        "value": "",
        "regex": false
    }
}

您的 Datatables 类具有正确的装饰(参见上面的 DTOrderDir):

public class DTParameters
{
    public int Draw { get; set; }
    public DTColumn[] Columns { get; set; }
    public DTOrder[] Order { get; set; }
    public int Start { get; set; }
    public int Length { get; set; }
    public DTSearch Search { get; set; }
    public IEnumerable<string> AdditionalValues { get; set; }
}

public class DTColumn
{
    public string Data { get; set; }
    public string Name { get; set; }
    public bool Searchable { get; set; }
    public bool Orderable { get; set; }
    public DTSearch Search { get; set; }
}

public class DTOrder
{
    public int Column { get; set; }
    public DTOrderDir Dir { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum DTOrderDir
{
    ASC,
    DESC
}

public class DTSearch
{
    public string Value { get; set; }
    public bool Regex { get; set; }
}

阅读此处了解更多信息:JavaScriptSerializer - JSON serialization of enum as string

【讨论】:

    猜你喜欢
    • 2020-10-12
    • 1970-01-01
    • 2021-09-19
    • 2021-08-27
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    相关资源
    最近更新 更多