.Net Core API — привязка смешанной модели не работает

Используется фреймворк .Net Core 3.0, но тестировался в версии 2.2 и показал такое же поведение.

Я использую класс для автоматической привязки свойств запроса тела, и это работает очень хорошо, даже без атрибута [FromBody].

Теперь я добавил в этот класс новое свойство, которое будет соответствовать свойству из заголовка, и оно будет работать, если я использую его непосредственно в контроллере, например:

public IActionResult Test(TestRequest request, [FromHeader(Name = "Authorization")] string token)

Однако, когда я пытаюсь получить тот же результат, добавляя атрибут [FromHeader] в свойство класса, это не работает.

Вот пример кода, иллюстрирующий проблему:

[ApiController]
[Route("api")]
public class TestController : ControllerBase
{
    [HttpPost]
    [Route("Test")]
    public IActionResult Test(TestRequest request)
    {
        Console.WriteLine("request.UserId: " + request.UserId);
        Console.WriteLine("request.Token: " + request.Token);
        return Ok();
    }
}
public class TestRequest
{
    [FromBody]
    public string UserId { get; set; }

    [FromHeader(Name = "Authorization")]
    public string Token { get; set; }
}

Кто-нибудь когда-нибудь сталкивался с той же проблемой?


person Leandro Bremer    schedule 25.09.2019    source источник
comment
Можете ли вы устранить путаницу, вы говорите добавлено новое свойство в этот класс, которое будет соответствовать свойству из заголовка, и оно работает, если я использую его непосредственно в контроллере, как это, а затем говорите Я пытаюсь получить тот же результат, добавляя атрибут [FromHeader] в свойство класса, это не работает. - но в обоих случаях вы показываете один и тот же код   -  person Jeremy Thompson    schedule 26.09.2019
comment
Вы пытались удалить [FromHeader(Name = "Authorization")] string token?   -  person Chetan Ranpariya    schedule 26.09.2019
comment
@JeremyThompson уверен, что полный код содержит оба подхода, используя атрибут FromHeader в контроллере, а также в классе. Таким образом, вы можете увидеть, что работает (контроллер), а что нет (класс). Посмотрите на изображение, которое я разместил, чтобы увидеть результаты, пожалуйста!   -  person Leandro Bremer    schedule 26.09.2019
comment
@ChetanRanpariya Да, на самом деле, как я только что упомянул Джереми, это полный код, содержащий оба подхода. Я пытался использовать только один из них и оба, но работает только контроллер.   -  person Leandro Bremer    schedule 26.09.2019
comment
@LeandroBremer, у вас была возможность просмотреть ссылку привязка модели в ASP.NET Core   -  person Nkosi    schedule 26.09.2019
comment
@ Нкоси да, я сделал. В нем говорится, что можно использовать так (в свойстве класса), но, к сожалению, это не работает. знак равно   -  person Leandro Bremer    schedule 26.09.2019
comment
@LeandroBremer, не могли бы вы указать мне место в справочнике MSDN, где говорится, что его можно использовать следующим образом (свойство класса)?   -  person Jeremy Thompson    schedule 26.09.2019
comment
@JeremyThompson это предложение: добавляются к свойствам модели индивидуально (не к классу модели), как в следующем примере [FromQuery(Name =Note)]   -  person Leandro Bremer    schedule 26.09.2019


Ответы (1)


Вам нужно настроить SuppressInferBindingSourcesForParameters как true в ConfigureServices в Startup.cs, как показано ниже:

services.AddMvc().ConfigureApiBehaviorOptions(options =>
        {
            options.SuppressInferBindingSourcesForParameters = true;
        });

Действие:

[HttpPost]
[Route("Test")]
public IActionResult Test(TestRequest request)

И вызовите API с вашим заголовком Authorization (не показано ниже) и строкой тела для почтальона введите здесь описание изображения

Обновление:

Поскольку вы используете [FromBody] для строкового свойства, оно принимает строку вместо объекта json.

Если вы все еще хотите передать объект json как { "userId" : "123" }, вы можете деформировать userId в модель, например:

public class User
{
    public string UserId { get; set; }
}
public class TestRequest
{
    [FromBody]
    public User User { get; set; }

    [FromHeader(Name = "Authorization")]
    public string Token { get; set; }
}
person Ryan    schedule 26.09.2019
comment
это сработало!!! Однако мой запрос Json перестал работать. Я получил неверный запрос, и мне нужно было изменить формат тела запроса, исключая скобки и имя параметра... с этого { "userId" : "123" } на этот "123" ...=/ ... Знаете ли вы, есть ли способ сохранить тот же формат работающий? Я использую .Net Core 3.0 - person Leandro Bremer; 26.09.2019
comment
@Leandro Bremer Это потому, что вы добавляете [FromBody] к свойству, поэтому вам нужно передать строку вместо объекта. См. github.com/aspnet/AspNetCore.Docs/issues/11699 - person Ryan; 27.09.2019
comment
@Leandro Bremer, если вы хотите передать его как объект, вам нужно обернуть userId в модель представления. Смотрите мое обновление. - person Ryan; 27.09.2019
comment
@Leandro Bremer Не могли бы вы принять ответ, если решили проблему? Спасибо! - person Ryan; 30.09.2019
comment
Это сработало правильно!! Мне придется изменить свой код здесь, однако, он будет действительно структурирован! Спасибо, мужик! - person Leandro Bremer; 02.10.2019