これが機能する理由を知っていますか:
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と.passwordはどちらもnullです。
コントローラーでタプルを使用することはできませんか?
名前付きタプルの名前は完全に「本物」ではないため、機能しません。コンパイラが提供する構文糖がほとんどです。 ValueTuple
型のセットを見ると、名前付きタプルがそれによって表され、Item1
、Item2
などのプロパティがあることがわかります。
コンパイラーは、名前付きタプル名へのすべての参照を実際の名前(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
属性を使用できるカスタムバインダーを作成できますが、実際にはそうする必要はありません。コメントで提案されているように、個別のパラメータまたは実際のモデルを使用してください。アクション入力パラメーターは使い捨てのものではありません。後でそれらを検証したり、モデルからドキュメントを生成したりすることができます。
this パッケージを使用できます。このパッケージは、json本体をモデルにバインドします。
//Nuget
Install-Package M6T.Core.TupleModelBinder -Version 1.0.0
//dotnet cli
dotnet add package M6T.Core.TupleModelBinder --version 1.0.0
のようなstartup.csを変更します
using M6T.Core.TupleModelBinder;
....
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new TupleModelBinderProvider());
});
}
投稿リクエスト本文
{
"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});
}
}