Home > Enterprise >  Viewmodel not being passed to controller post method? ASP.NET
Viewmodel not being passed to controller post method? ASP.NET

Time:07-11

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:

  1. The Select Tag Helper asp-for specifies the model property name for the select element and asp-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 by Id property.

  2. You cannot pass whole complex model by asp-for.

  3. 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");}
}

Result: enter image description here

  • Related