在ASP.NET核心Web API控制器使用C#7元组

问题描述 投票:7回答:2

你知道为什么这个工程:

    public struct UserNameAndPassword
    {
        public string username;
        public string password;
    }


    [HttpPost]
    public IActionResult Create([FromBody]UserNameAndPassword usernameAndPassword)
    {
        Console.WriteLine(usernameAndPassword);
        if (this.AuthenticationService.IsValidUserAndPasswordCombination(usernameAndPassword.username, usernameAndPassword.password))
            return new ObjectResult(GenerateToken(usernameAndPassword.username));
        return BadRequest();
    }

但是,当我有一个元组替换它,这也不行?

     [HttpPost]
    public IActionResult Create([FromBody](string username, string password) usernameAndPassword) //encrypt password?
    {
        Console.WriteLine(usernameAndPassword);
        if (this.AuthenticationService.IsValidUserAndPasswordCombination(usernameAndPassword.username, usernameAndPassword.password))
            return new ObjectResult(GenerateToken(usernameAndPassword.username));
        return BadRequest();
    }

usernameAndPassword.username和。密码都为空。

你是不是允许控制器使用的元组?

c# asp.net-core tuples asp.net-core-webapi c#-7.0
2个回答
13
投票

这是行不通的,因为命名的元组的名字是不是很“真实”,它主要是由编译器提供的语法糖。如果你看一下ValueTuple集的类型,通过一个名为元组的代表,你会发现它们有像Item1Item2等特性。

编译器将命名元组的名称所有引用改写为他们的真实姓名(Item1等)。例如,你有这样的:

static void Create((string username, string password) usernameAndPassword) {
    Console.WriteLine(usernameAndPassword.username);
    Console.WriteLine(usernameAndPassword.password);
}

但是,当您编译,你真的会是这样的:

static void Create([TupleElementNames(new string[] {"username", "password"})] ValueTuple<string, string> usernameAndPassword)
{
  Console.WriteLine(usernameAndPassword.Item1);
  Console.WriteLine(usernameAndPassword.Item2);
}

你的名字是现在唯一的元数据属性TupleElementNames,但不是在代码。

出于这个原因,当你发布这样的:

{"username": "x", "password": "y"}

到你的动作,asp.net不能结合。但是,如果你将发布:

{"item1": "x", "item2": "y"}

然后它会没有问题绑定。你或许可以编写自定义的粘合剂,它可以使用TupleElementNames属性,但没有理由真的。只要使用单独的参数或实际模型作为意见提出。你的动作输入参数是不是有些暴殄天物的事情。你可能以后要验证它们,从模型中生成等文档。


2
投票

您可以使用this包。该软件包结合json的身体你的模型。

Github Repo

安装

//Nuget
Install-Package M6T.Core.TupleModelBinder -Version 1.0.0

//dotnet cli
dotnet add package M6T.Core.TupleModelBinder --version 1.0.0

Usage

修改像startup.cs

using M6T.Core.TupleModelBinder;
....

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc(options =>
  {
      options.ModelBinderProviders.Insert(0, new TupleModelBinderProvider());
  });
}

POST请求体

{
  "user" : {
    "Name":"Test",
    "Surname":"Test2",
    "Email":"[email protected]"
  },
  "someData" : "If you like it, you put a data on it"
}

而在你的控制器使用它像

[HttpPost]
public IActionResult CreateUser((User user, string someData) request)
{
    using (var db = new DBContext())
    {
        var newUser = db.Users.Add(request.user);
        db.SaveChanges();
        return Json(new { userId = request.user.Id, someData = request.someData});
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.