#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 Затем ядро обнаружило, что данные формы соответствуют имени параметра, и затем оно начало привязываться должным образом. Моя проблема была решена.