I'm having some problems with returning a viewmodel to my controller's create post method in asp.net 6, the viewmodel seems to always be empty and I've run to a dead end debugging.
I'm trying to upload some images and send them to my post method in the controller.
Specifically the create(ArtImages vm) seems to be null.
If anything is unclear or I need to add anything let me know.
Artwork model:
public class Artwork
{
public int Id { get; set; }
public string Information { get; set; }
public ICollection<ArtworkImage> ArtworkImage { get; set; }
}
ArtworkImage model:
public class ArtworkImage
{
public int Id { get; set; }
public string ImageURL { get; set; }
public Artwork Artwork { get; set; }
}
ArtImages viewmodel:
public class ArtImages
{
public List<IFormFile> Images { get; set; }
public Artwork Artwork { get; set; }
}
Create artworkImages view:
@model website.ViewModel.ArtImages
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>ArtworkImage</h4>
<hr />
<div >
<div >
<form asp-action="Create" encrypte="multipart/form-data" asp-controller="ArtworkImages">
<div asp-validation-summary="ModelOnly" ></div>
<div >
<label asp-for="Artwork" ></label>
<select asp-for="Artwork" asp-items="@ViewBag.images" >
<option value="0">Select artwork</option>
</select>
<span asp-validation-for="Artwork" ></span>
</div>
<div >
<label asp-for="Images" ></label>
<input asp-for="Images" multiple />
<span asp-validation-for="Images" ></span>
</div>
<div>
<input type="submit" value="Create" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
GET: ArtworkImages/Create:
public IActionResult Create(int id)
{
ArtImages vm = new ArtImages();
ViewBag.images = new SelectList(_context.Artworks.Where(m => m.Id == id).ToList(), "Id", "Information");
return View(vm);
}
POST: ArtworkImages/Create:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(ArtImages vm)
{
foreach (var item in vm.Images)
{
string stringFileName = UploadFile(item);
var artworkImage = new ArtworkImage
{
ImageURL = stringFileName,
Artwork = vm.Artwork
};
_context.ArtworkImages.Add(artworkImage);
}
_context.SaveChanges();
return RedirectToAction("Index");
}
CodePudding user response:
try using
public async Task<IActionResult> Create([FromForm]ArtImages vm)
CodePudding user response:
The Select Tag Helper
asp-for
specifies the model property name for the select element andasp-items
specifies the option elements.Your select option here generate the data by the following code:
ViewBag.images = new SelectList(_context.Artworks.Where(m => m.Id == id).ToList(), "Id", "Information");
It will generate the option text by
Information
property and option value byId
property.You cannot pass whole complex model by
asp-for
.The backend will receive the value of the element.
In summary:
The asp-for
should be Artwork.Id
.
Note:
Besides, you mispell encrypte="multipart/form-data"
, it should be enctype="multipart/form-data"
.
The whole working demo:
View:
@model ArtImages
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>ArtworkImage</h4>
<hr />
<div >
<div >
//change here.....
<form asp-action="Create" enctype="multipart/form-data" asp-controller="ArtworkImages">
<div asp-validation-summary="ModelOnly" ></div>
<div >
<label asp-for="Artwork" ></label>
//change here....
<select asp-for="Artwork.Id" asp-items="@ViewBag.images" >
<option value="0">Select artwork</option>
</select>
<span asp-validation-for="Artwork.Id" ></span>
</div>
<div >
<label asp-for="Images" ></label>
<input asp-for="Images" multiple />
<span asp-validation-for="Images" ></span>
</div>
<div>
<input type="submit" value="Create" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}