Использование кортежа C # 7 в контроллере ASP.NET Core Web API - PullRequest
0 голосов
/ 24 апреля 2018

Знаете ли вы, почему это работает:

    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.

Вам не разрешено использовать кортежи в контроллере?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Вы можете использовать этот пакет.Этот пакет привязывает тело 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

Использование

Изменение файла 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":"example@example.com"
  },
  "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});
    }
}
0 голосов
/ 24 апреля 2018

Это не работает, потому что именованные имена кортежей не совсем "настоящие", это в основном синтаксический сахар, предоставляемый компилятором. Если вы посмотрите на 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, но для этого нет никаких оснований. Просто используйте отдельные параметры или реальную модель, как это предлагается в комментариях. Ваши входные параметры действий не являются чем-то одноразовым. Позже вы можете захотеть проверить их, сгенерировать документацию из модели и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...