【问题标题】:Controller post [FromBody] Null issue when when migrating from .netcore 2.2 to 3.0从 .net core 2.2 迁移到 3.0 时,控制器发布 [FromBody] Null 问题
【发布时间】:2020-04-19 07:13:53
【问题描述】:

我在 2.2 版有一个功能齐全的程序 迁移到 3.0 版并替换时

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddMvc();
}

services.AddControllers();

并替换app.UseMvc();

与:

app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

其中一个控制器坏了。 (其他也有 Post Method 和 [FromBody] 的控制器工作正常) 破坏的控制器和方法是:

[Route("api/vm")]
public class MainController: Controller
{
    [HttpPost]
    [Route("Process")]
    public IActionResult GetProcess([FromBody]ProcessModel[] process)
    {
         ...
    }
}

模型:

public class ProcessModel
{
    [JsonProperty("Name")]
    public string Name { get; set; }
    [JsonProperty("ExeName")]
    public string ExeName { get; set; }
    [JsonProperty("Path")]
    public string Path { get; set; }
    [JsonProperty("VersionPath")]
    public string VersionPath { get; set; }
    [JsonProperty("Id")]
    public string Id { get; set; }
    [JsonProperty("Status")]
    public string Status { get; set; }
    [JsonProperty("Ver")]
    public string Ver { get; set; }
    [JsonProperty("Args")]
    public string[] Args { get; set; }
    [JsonProperty("Instances")]
    public List<ProcessDetails> Instances { get; set; }
    [JsonProperty("Multiple")]
    public string Multiple { get; set; }
}  

我正在打给/api/vm/Process的电话:

[
    {
        "Name": "Test",
        "ExeName": "Test",
        "Multiple": false,
        "Path": "Test",
        "VersionPath": "Test",
        "Args": {
            "IsFile": false
        }
    },
    {
        "Name": "Test",
        "ExeName": "Test.exe",
        "Multiple": false,
        "Path": "Test",
        "VersionPath": "Test",
        "Args": {
            "IsFile": false
        }
    }
]

该应用在生产环境中运行了几个月。我所做的只是升级到 .netcore 3,现在当我调试并进入控制器上的方法时,我在进程变量中得到 null

注意: 当应用程序首先被破坏时,我使用了这个线程 Using 'UseMvc' to configure MVC is not supported while using Endpoint Routing

【问题讨论】:

  • 一种可能的情况是:Multiple 在模型中被声明为字符串,但在 JSON 中您作为布尔值传递。声明布尔值或将 false 分配为字符串 "Multiple": "false",
  • 这是您模型的可能字符串: [ { "Name": "Test", "ExeName": "Test", "Multiple": "false", "Path": "Test" , "VersionPath": "Test", "Args": ["false"] }, { "Name": "Test", "ExeName": "Test.exe", "Multiple": "false", "Path" : "Test", "VersionPath": "Test", "Args": ["false"] } ]
  • 如果您的 json 出价在 .net 2 中工作,请尝试使用 newtonsoft,如此处所述docs.microsoft.com/en-us/aspnet/core/migration/…
  • 是的,听起来像是 system.text.json 更改。
  • 不是您问题的答案,但如果您的属性名称与 JSON 键相同,则无需使用 JsonProperty

标签: c# asp.net-core asp.net-mvc-controller


【解决方案1】:

自动类型转换在新的System.Text.Json 中不可用,可能是出于性能原因。您应该使用“Newtonsoft 序列化程序”或使用自定义转换器。您的一些类属性是字符串,但您发送的是 bool(多个属性),int。

使用 Newtonsoft: https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio#jsonnet-support

System.Text.Json转换器示例:

https://github.com/dotnet/corefx/blob/master/src/System.Text.Json/tests/Serialization/CustomConverterTests.Int32.cs

像这样注册您的转换器:

services.AddControllers().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.Converters.Add(new MyInt32Converter());
});
【解决方案2】:

原因是你的ProcessModelstring[] 类型的Args

public string[] Args { get; set; }

在您的 json 中,您将其作为对象传递,这会导致模型绑定为空

"Args": {
        "IsFile": false
    }

Args 传递为string[] 喜欢

"Args": ["IsFile:false"]

或者如果您确实想更改 json,请将 Args 修改为 Dictionary 类型:

[JsonProperty("Args")]      
public Dictionary<string, string> Args { get; set; }

记得像其他人所说的那样添加对NewtonsoftJson的引用

services.AddControllers().AddNewtonsoftJson();

【讨论】:

    【解决方案3】:

    MultipleArgs JSON 属性中的问题。
    在 JSON 中它们是 bool 和 object,但在 Process 模型中它们都是字符串。我不太确定它如何在 Core 2.2 中工作。

    【讨论】:

      【解决方案4】:

      第 1 步: 在 Visual Studio for Mac 中下载并安装“Microsoft.AspNetCore.Mvc.NewtonsoftJson”NuGet 包 - 我使用的是 Macbook Pro。

      第 2 步: 我已阅读 Migrate Startup.Configure 将我的项目迁移到 .Net Core 3。基本上您需要做的就是在 ConfigureServices() 方法的现有设置中添加以下内容:

      public void ConfigureServices(IServiceCollection services)
      {
          // update Startup.ConfigureServices to call AddNewtonsoftJson
          services.AddControllers();
          ...
          ...
          services.AddMvc()
                  .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
                  .AddNewtonsoftJson(); 
      }
      

      然后在 Configure() 方法上添加以下内容:

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          ...
          ...
          app.UseRouting();
          app.UseCors();
      
          app.UseAuthentication();
          app.UseAuthorization();
      
          app.UseEndpoints(endpoints => {
              endpoints.MapControllers();
          });
      }
      

      这些截图来自微软:

      第 3 步:从方法签名中删除 FromBody。 .Net Core 3+ 不再需要它。所以你的终点应该是这样的:

      [HttpPost("Login")]
      public IActionResult Login(YourRequest request) {
      
      }
      

      另外,我没有将 [JsonProperty] 属性添加到模型属性中。我的请求类结构是:

      using System;
      
      namespace Models.Communication.Request
      {
          public class LoginRequest
          {
              public String Email { get; set; }
              public String Password { get; set; }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-05
        • 2020-02-19
        • 2020-05-28
        • 1970-01-01
        • 2020-01-26
        • 2021-09-02
        相关资源
        最近更新 更多