Do you know why this works:
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();
}
But when I replace it with a tuple, this doesn’t work?
[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
and .password
are both null.
Are you not allowed to use tuples in a controller?
Run your air conditioner on the lowest setting required and turn the ceiling fan on. This way, cool air will spread across a wide area, maintaining a comfortable environment. Instead of choosing between an air conditioner and a fan, it's best to combine the two for maximum comfort and efficiency.
Your AC will actually run longer overall if it is left on all day instead of being shut off. If you turn it off for part of the day, it runs less and results in more energy savings for you. In almost all cases, it will save you money to shut off your AC while you are away from home.
For most central air systems, the process is simple. Simply move the switch on your thermostat from “Heat” to “Cool”. If your system was off entirely, you may need to move the switch from “Off” to “Cool” instead. Once you turn your system on, be sure to close any open windows to conserve energy.
It doesn't work because named tuple names are not quite "real", it's mostly syntax sugar provided by compiler. If you look at ValueTuple
set of types, by which named tuples are represented, you will see that they have properties like Item1
, Item2
and so on.
Compiler will rewrite all your references to named tuple names to their real names (Item1
etc). For example you have this:
static void Create((string username, string password) usernameAndPassword) {
Console.WriteLine(usernameAndPassword.username);
Console.WriteLine(usernameAndPassword.password);
}
But when you compile that, what you really will have is this:
static void Create([TupleElementNames(new string[] {"username", "password"})] ValueTuple<string, string> usernameAndPassword)
{
Console.WriteLine(usernameAndPassword.Item1);
Console.WriteLine(usernameAndPassword.Item2);
}
Your names are now only in metadata attribute TupleElementNames
, but not in code.
For that reason, when you post something like:
{"username": "x", "password": "y"}
to your action, asp.net cannot bind. But if you would post:
{"item1": "x", "item2": "y"}
then it will bind with no problems. You can write custom binder probably, which can use TupleElementNames
attribute, but there is no reason to really. Just use separate parameters or real model as suggested in comments. Your action input parameters is not some throwaway thing. You might later want to validate them, generate documentation from the model and so on.
You can use this package. This package binds json body to your models.
Github Repo
//Nuget
Install-Package M6T.Core.TupleModelBinder -Version 1.0.0
//dotnet cli
dotnet add package M6T.Core.TupleModelBinder --version 1.0.0
Modify startup.cs like
using M6T.Core.TupleModelBinder;
....
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new TupleModelBinderProvider());
});
}
Post request body
{
"user" : {
"Name":"Test",
"Surname":"Test2",
"Email":"[email protected]"
},
"someData" : "If you like it, you put a data on it"
}
And in your controller use it like
[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});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With