Asp.net базовая модель не привязывается к форме

#c# #asp.net #forms #asp.net-core #model-binding

#c# #asp.net #формы #asp.net-core #привязка к модели

Вопрос:

Я перехватываю запрос post со статической страницы третьей стороны (сгенерированной Adobe Muse) и обрабатываю его с помощью действия MVC.

 <form method="post" enctype="multipart/form-data">
   <input type="text" name="Name">
   ...
</form>
  

Маршрутизация для действия с пустой формой:

 app.UseMvc(routes => routes.MapRoute(
   name: "default",
   template: "{controller=Home}/{action=Index}"));
  

Но в соответствии с действием у меня есть модель, каждое свойство которой пусто

Экшен:

 [HttpPost]
public void Index(EmailModel email)
{
   Debug.WriteLine("Sending email");
}
  

Модель:

 public class EmailModel
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Company { get; set; }
    public string Phone { get; set; }
    public string Additional { get; set; }
}
  

Request.Form содержит все значения из формы, но модель пуста

 [0] {[Name, Example]}
[1] {[Email, Example@example.com]}
[2] {[Company, Hello]}
[3] {[Phone, Hello]}
[4] {[Additional, Hello]}
  

Комментарии:

1. Почему вы используете enctype="multipart/form-data" ? Вам не нужно указывать это, потому что ваша модель не содержит никакой загрузки файлов. Вероятно, ваша проблема вызвана этим. Удалите и попробуйте.

2. @ademcaglin удалил enctype атрибут. Не помогает. По-прежнему Request.Form имеет все значения, но model пуста.

3. Вы использовали какой-либо код javascript для отправки формы?

4. @ademcaglin нет, просто отправляйте чистую форму

Ответ №1:

Будьте осторожны, чтобы не присвоить параметру действия имя, совпадающее со свойством модели, иначе связующее устройство попытается привязаться к параметру и потерпит неудачу.

 public async Task<IActionResult> Index( EmailModel email ){ ... }

public class EmailModel{ public string Email { get; set; } }
  

Измените параметр actions ’email’ на другое имя, и он будет привязан, как ожидалось.

 public async Task<IActionResult> Index( EmailModel uniqueName ){ ... }
  

Комментарии:

1. Спасибо! У меня было свойство с именем «Model» в моей модели представления, которое нарушило привязку.

2. Похоже ASP.NET Код привязки модели ядра мог бы бросить нам кость, возможно, создав исключение в этом случае!

3. Я имею в виду … Вау.. Это то, что я не смог найти самостоятельно.

4. Ты мой ангел!

5. Что ж, это час бессмысленной отладки, к которому я никогда не вернусь.

Ответ №2:

Я не уверен, что это тот же случай, но у меня была такая же проблема, и, похоже, у меня ничего не работает.
Проблема в моем случае заключалась в том, что у меня было свойство с именем Model в моем классе view model

 public string Model { get; set; }
  

Когда я переименовал свойство в ModelName, все снова работало нормально, даже без атрибута FromForm.

Похоже, что некоторые специальные имена свойств могут быть небольшой проблемой для asp.net привязка модели mvc.

Итак, мой совет — проверить свойства вашей модели и, возможно, попробовать переименовать их одно за другим, чтобы проверить, есть ли проблема.

Надеюсь, это поможет.

Ответ №3:

ASP.Net Ядро 3.1

В моем случае я использовал сложную модель (модель, которая содержит другие модели, например, общую модель), размещенную Ajax, поэтому входные данные в представлении автоматически назывались следующим образом «Дочерняя модель».propertyName» (см. Код)

    [HttpPost]
   [ValidateAntiForgeryToken] // ("AUVM.PropertyName")
   public async Task<JsonResult> AddUser([FromForm]AUVM aUVM) //Parameter name must match the first part of the input name in order to bind
   {

   }
  
    [HttpPost]
   [ValidateAntiForgeryToken]
   public async Task<JsonResult> AddUser([FromForm]AUVM someUniqueName) //This is wrong and won't bind
   {

   }
  

Ответ №4:

У меня такая же проблема, этот документ помогает мне понять привязку моделиhttps://docs.asp.net/en/latest/mvc/models/model-binding.html

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

Ответ №5:

Я столкнулся с этим сегодня, и хотя, оглядываясь назад, это кажется очевидным, просто подумал, что хотел бы добавить, что вам нужно убедиться, что ваши модификаторы доступа для свойств модели, которую вы привязываете, верны. У меня было public MyProperty { get; internal set; } на некоторых, и они не привязывались. Удалено internal , и они работали просто отлично.

Комментарии:

1. БОЖЕ, вот в чем проблема, с которой я столкнулся. Я бы никогда не разобрался в этом без вашей потрясающей помощи. Спасибо!!

Ответ №6:

Измените void на ActionResult.

 [HttpPost]
public ActionResult Index(EmailModel email)
  

И не забудьте проверить AntiForgeryToken из вашего представления и действия.

 // to your form in view 
@Html.AntiForgeryToken()
// ------------

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(EmailModel email)
  

Комментарии:

1. Не помогает. Также я не могу использовать AntiForgeryToken , потому что эта страница не моя и сгенерирована сторонними инструментами (Adobe Muse)

2. Я думаю, вы не можете получить ее как модель с помощью инструмента, который не находится в режиме действия. Вы можете попытаться получить значение с помощью метода form get, а не как модель. По именам параметров. Индекс (строковое имя, строковый адрес электронной почты, строковая компания, строковый телефон). И преобразуйте эти значения в вашу объектную модель в процедуре.

3. Я также думаю, что mvc не может найти model или что-то в этом роде, и да, я могу просто использовать кучу параметров action, или заполнить это с помощью Request.Form in action, или попытаться сделать это с помощью IModelBinder , я просто хочу понять, почему я не могу просто использовать привязку модели по умолчанию. Может быть, я пропустил некоторые соглашения?

Ответ №7:

Эта проблема также может возникнуть, если одно или более ваших свойств в модели запроса не удается привязать к приемлемому в модели запроса.

В моем случае я должен был передать List<string> тип свойству, но случайно передал string . Это привело к тому, что вся модель запроса стала null

Ответ №8:

В моем случае я использовал соглашение MVC 4.0 об именовании объекта, который вы публикуете. Например.,

js: $http.post("SaveAnswer", { answer: answerValues })

C#: public ActionResult SaveAnswer([FromBody] AnswerVM answer) {...}

Когда я изменил js на $http.post("SaveAnswer", answerValues) , все работает.

Ответ №9:

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

 public class EmailModel
{
    public EmailModel()
    {}

    public EmailModel(string _name, string _company)
    {
        Name = _name;
        Company = _company;
    }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Company { get; set; }
    public string Phone { get; set; }
    public string Additional { get; set; }
}
  

Исправлено путем удаления всех конструкторов, кроме одного, подобного этому:

 public class EmailModel
{
    public EmailModel()
    {}

    public string Name { get; set; }
    public string Email { get; set; }
    public string Company { get; set; }
    public string Phone { get; set; }
    public string Additional { get; set; }
}
  

Ответ №10:

У меня была такая же проблема, и я хочу поделиться тем, что произошло в моем случае, и как я получил решение. Возможно, кому-то будет полезно это знать.

Мой контекст был ASP.NET Страницы Razor в ядре 3.1. У меня был обработчик как

 public async Task<JsonResult> OnPostLogin([FromForm] LoginInput loginData)
{
  
}
  

а также у меня было свойство в моей ViewModel как

   public LoginInput LoginInput { get; set; }
  

И на моей странице Razor я использовал форму, подобную этой:

  <form asp-page-handler="Login" method="post">

 <input asp-for="LoginData.UserNameOrEmail">

 .....
 
        
  

Итак, обратите внимание, что в моей форме я использовал свойство LoginInput.UserNameOrEmail, но в параметре моего обработчика я использовал имя параметра loginData. Как будет ASP.NET Ядро знает это, это LoginInput.UserNameOrEmail на самом деле является loginData.UserNameOrEmail. Это невозможно, верно? Следовательно, она не привязывала данные моей формы.

Затем, когда я переименовал свое свойство ViewModel «LoginInput» на то же имя, что и параметр обработчика, вот так:

 public LoginInput LoginData { get; set; }
  

The ASP.NET Затем ядро обнаружило, что данные формы соответствуют имени параметра, и затем оно начало привязываться должным образом. Моя проблема была решена.