Отправка на другую модель из формы в ASP.NET MVC
Если у меня есть представление с моделью, скажем Car..
@model Project.Car
внутри этого представления Я хочу создать форму, которая отправляет данные в новую модель
@using (Html.BeginForm("Add", "Controller"))
{
@Html.Hidden("ID", "1")
@Html.Hidden("UserID", "44")
@Html.TextArea("Description")
}
Я заметил, что если мое действие определено с моим ViewModel, оно не работает (модель всегда равна нулю):
[HttpPost]
public PartialViewResult Add(ViewModels.NewModel model)
Однако, если я использую FormCollection, он работает:
[HttpPost]
public PartialViewResult Add(FormCollection formCollection)
Вот модель ViewModel:
public class NewModel
{
public int ID { get; set; }
public int UserID { get; set; }
public string Description { get; set; }
}
Мой вопрос: могу ли я отправить данные в NewModel из моей формы? Вид, на котором он сидит, правильно привязан к Project.Car. Его небольшая форма на странице, на которой должен размещаться другой набор данных, не имеющий ничего общего с Project.Car.
Ответы
Ответ 1
У вас есть несоответствие между именем вашей модели и вашим действием. В примере, который вы показали, модель называется Add
, тогда как в вашем действии вы используете ViewModels.NewModel
. Хуже того, ваш взгляд строго типизирован на модель под названием Car
. Беспощадно все это.
Итак, начните с определения правильной модели представления:
public class CarViewModel
{
public int ID { get; set; }
public int UserID { get; set; }
public string Description { get; set; }
}
а затем контроллер:
public class CarsController: Controller
{
public ActionResult Add()
{
var model = new CarViewModel
{
// don't ask me, those are the values you hardcoded in your view
ID = 1,
UserID = 44,
};
return View(model);
}
[HttpPost]
public PartialViewResult Add(CarViewModel model)
{
...
}
}
и соответствующий строго типизированный вид вашей модели представления:
@model CarViewModel
@using (Html.BeginForm())
{
@Html.HiddenFor(x => x.ID)
@Html.HiddenFor(x => x.UserID)
@Html.TextAreaFor(x => x.Description)
<button type="submit">Add</button>
}
Ответ 2
My question is can I post data to NewModel from my form?
Короткий ответ: да, вы можете отправить форму любому действию контроллера на любом контроллере, связанном с любой моделью в вашем приложении.
Например, для вашей формы для сообщения в действие "Add
" на контроллере NewModel
:
@using (Html.BeginForm("Add", "NewModel"))
{
@Html.Hidden("ID", "1")
@Html.Hidden("UserID", "44")
@Html.TextArea("Description")
}
Поскольку ваше представление строго типизировано для вашей модели Car
, вы можете либо изменить это, либо отправить ViewModel в ваше представление, тип которого соответствует модели вашего обновления (в качестве Дарин продемонстрировал), или вам нужно будет отобразить данные сообщения из Car
на NewModel
в вашем контроллере:
В CarController
Add
action (Post):
[HttpPost]
public PartialViewResult Add(Car model)
{
//now map attribute values from the Car model onto
//corresponding attributes of an instance of NewModel
NewModel new = new NewModel();
new.ID = model.ID;
new.UserID = model.UserID;
new.Desc = model.Description;
//etc...
//update your model/db
_db.Add(new);
//Redirect however you wish...
}
Кроме того, проверьте AutoMapper, объект-объект mapper, который автоматизирует отображение ViewModels на Модели и наоборот.
Ответ 3
Да, вы можете сильно набрать представление одной модели и отправить ее в другую модель.
При этом у вас есть два варианта:
-
Вручную укажите правильные имена для каждого поля ввода, чтобы связующее по умолчанию понимало его и создавало модель (пример).
В то время как это работает, это также означает, что вы должны следить за опечатками, и вы не получите ошибок во время компиляции, если вы пропустили имя свойства.
-
Вручную создайте HTML-помощник в представлении, связанного с новым типом модели. Затем он будет правильно генерировать HTML для вас.
Чтобы создать помощник, вам понадобится объект-оболочка, который выведет экземпляр вашей модели в виде интерфейса IViewDataContainer
. Вы можете определить эту оболочку в любом месте, включая сама модель:
public class NewModel
{
public int ID { get; set; }
public int UserID { get; set; }
public string Description { get; set; }
public class WrapperForHtmlHelper : System.Web.Mvc.IViewDataContainer
{
public System.Web.Mvc.ViewDataDictionary ViewData { get; set; }
public WrapperForHtmlHelper(NewModel value)
{
this.ViewData = new System.Web.Mvc.ViewDataDictionary<NewModel>(value);
}
}
}
Затем в представлении создается помощник, связанный с экземпляром NewModel
:
var ModelToPost = new YourApp.Models.NewModel() { ID = 1, UserID = 43, Description = "" }
var hlp = new HtmlHelper<YourApp.Models.NewModel>
(this.ViewContext,
new YourApp.Models.NewModel.WrapperForHtmlHelper(ModelToPost)
);
И затем вы используете помощника, как обычно:
@hlp.HiddenFor(m => m.ID)
@hlp.HiddenFor(m => m.UserID)
@hlp.TextAreaFor(m => m.Description)
Затем ваш PartialViewResult Add(ViewModels.NewModel model)
будет правильно получать данные.
Ответ 4
В вашем представлении используется модель типа Project.Car
однако, в вашем методе действий используется модель типа ViewModels.NewModel
, , а также опубликованный класс модели имеет тип Add
?
Измените все, чтобы они совпадали (при условии, что Add
правильный):
Вид:
@model Add
Контроллер:
[HttpPost]
public PartialViewResult Add(Add model)
Ответ 5
Для этой цели также можно создать настраиваемое связующее устройство.