First of all, this is a simplified version of my problem.
I have two models:
- Person
- Category
The problem is that I need two models. I have a form where I show the categories in a select input to then create a new Person.
In .cshtml i have:
@using WebApiClient.Models
@model dynamic
<h1> Form: add a person with a category</h1>
<form asp-action="formMultiple" enctype="multipart/form-data" method="post">
<label [email protected] >Name</label>
<input asp-for="@Model.Person.Name" value= "@Model.Person.Name" />
<label asp-for="Category" >Category</label>
<select asp-for="Category">
@foreach (var item in Model.Category){
<option value="Category">@item.NameCategory</option>
}
</select>
<input type="submit" value="Add person" />
</form>
And i have in controller:
public async Task<IActionResult> formMultiple()
{
dynamic d = new ExpandoObject();
var categories = await _client.GetCategoriesAsync();
d.categories = categories;
d.person = new Person();
return View(d);
}
public async Task<ActionResult> formMultiple(Person person);
Any ideas how to solve this problem? Thank you <3
CodePudding user response:
Based on a comment above:
CS1963 An expression tree may not contain a dynamic operation
Don't rely on dynamic
for your view models. It's trivial to create classes which give you all of the static type safety that C# generally expects. dynamic
can be a useful tool, but is not a drop-in replacement for anywhere you don't want to create a class.
Your view model could be as simple as (I'm guessing on a reasonable name):
public class CreatePersonVM
{
public IEnumerable<Category> Categories { get; set; }
public Person Person { get; set; }
}
Then you'd expect that type in the view:
@model CreatePersonVM
And supply it from the controller:
var model = new CreatePersonVM();
model.Categories = await _client.GetCategoriesAsync();
model.Person = new Person();
return View(model);
Just ensure that the elements in the <form>
still create a Person
object and that form can still post the values for that object to the POST action.
CodePudding user response:
There are couple of options
- Use a ViewModel with two properties (One for Person and One for Categories) - Best and Recommended option
- Use a ValueTuple with two items (One for Person and One for Categories) - It should be used for small amount of data
- Send Person Model to the view and have Categories in ViewBag or ViewData
- Send Person Model to the view and have an ajax call to fill the Categories dropdown
So I can give you sample for the second approach
Controller
public async Task<IActionResult> formMultiple()
{
var categories = await _client.GetCategoriesAsync();
var person = new Person();
var model = (person, categories);
return View(model );
}
View
@using WebApiClient.Models
@model (Person person, List<Category> categories)
<h1> Form: add a person with a category</h1>
<form asp-action="formMultiple" enctype="multipart/form-data" method="post">
<label asp-for=person.Name >Name</label>
<input asp-for="person.Name" />
<label asp-for="person.Category" >Category</label>
<select asp-for="person.Category">
@foreach (var item in Model.categories){
<option value="@item.IdCategory">@item.NameCategory</option>
}
</select>
<input type="submit" value="Add person" />
</form>
If you can share your Person and Category model, then I can provide more precise code