Home > database >  why is my foreign key model not validating?
why is my foreign key model not validating?

Time:08-19

Having started studying asp net core 6, I ran into the problem of invalidity of my model. What is the hidden problem?

Model of Product

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TestWebApplication.Models
{
    public class Product
    {
        [Key]
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        public string Description { get; set; }
        [Range(0.1, int.MaxValue)]
        public double Price { get; set; }
        public string Image { get; set; }
        [Display(Name = "Category Type")]
        public int CategoryId { get; set; }
        [ForeignKey("CategoryId")]
        public virtual Category Category { get; set; } 
    }
}

Model of ProductVM

using Microsoft.AspNetCore.Mvc.Rendering;

namespace TestWebApplication.Models.ViewModels
{
    public class ProductVM
    {
        public Product Product { get; set; }

        public IEnumerable<SelectListItem> CategorySelectList { get; set; }
    }
}

View

@model TestWebApplication.Models.ViewModels.ProductVM

@{
    var title = "Create Product";
}

<form method="post" enctype="multipart/form-data">
    @if(Model.Product.Id != 0)
    {
        title = "Edit Product";
        <input asp-for="Product.Id" hidden />   
    }
    <div >
        <div >
            <h2 >@title</h2>
        </div>
        <br />
        <div >
            <div >
                <div >
                    <div >
                        <label asp-for="Product.Name"></label>
                    </div>
                    <div >
                        <input asp-for="Product.Name" />
                        <span asp-validation-for="Product.Name" ></span>
                    </div>

                </div>
                <br />
                <div >
                    <div >
                        <label asp-for="Product.Price"></label>
                    </div>
                    <div >
                        <input asp-for="Product.Price" />
                        <span asp-validation-for="Product.Price" ></span>
                    </div>

                </div>
                <br />
                <div >
                    <div >
                        <label asp-for="Product.Description"></label>
                    </div>
                    <div >
                        <textarea asp-for="Product.Description" > </textarea>
                        <span asp-validation-for="Product.Description" ></span>
                    </div>

                </div>
                <br />
                <div >
                    <div >
                        Image
                    </div>
                    <div >
                        <input type = "file" name="files" id="uploadBox" multiple />
                    </div>

                </div>
                <br />
                <div >
                    <div >
                        <label asp-for="Product.CategoryId"></label>
                    </div>
                    <div >
                        <select asp-for="Product.CategoryId" asp-items="@Model.CategorySelectList" >
                            <option disabled selected>---Select Category---</option>
                        </select>
                        <span asp-validation-for="Product.CategoryId" ></span>
                    </div>
                </div>
                <br />
                <div >
                    <div >

                        <div >
                            @if (Model.Product.Id != 0)
                            {
                                //update
                                <input type="submit"  value="Update"/>
                            }
                            else
                            {
                                //create
                                <input type="submit" onclick="return validateInput()"  value="Create"/> 
                            }
                            
                        </div>
                        <div >
                            <a asp-action="Index" >
                                Back
                            </a> 
                        </div>
                    </div>
                </div>
            </div>
            <div >
                @* Keep this empty *@
            </div>
        </div>
    </div>
</form>

@section Scripts
{
    @{ 
    <partial name= "_ValidationScriptsPartial.cshtml"/> 
    }
    <script>
        $(document).ready(function() {
        $('.summernote').summernote(
            {
                height:250
            });
        });
        function validateInput()
        {
            if (document.getElementById("uploadBox").value == "")
            {
                Swal.fire
                (
                    'Error!',
                    'Please, upload an image',
                    'error'
                )
                return false;
            }
            return true;
        }
    </script>
}

Controller

using TestWebApplication.Data;
using TestWebApplication.Models;
using TestWebApplication.Models.ViewModels;

namespace TestWebApplication.Controllers
{
    public class ProductController : Controller
    {
        private readonly ApplicationDbContext _db;
        private readonly IWebHostEnvironment _webHostEnvironment;
        public ProductController(ApplicationDbContext db, IWebHostEnvironment webHostEnvironment)
        {
            _db = db;
            _webHostEnvironment = webHostEnvironment;
        }

        public IActionResult Index()
        {
            IEnumerable<Product> objList = _db.Product;

            foreach (var item in objList)
            {
                item.Category = _db.Category.FirstOrDefault(category => category.Id == item.Id);
            }

            return View(objList);
        }

        // get - upsert
        public IActionResult Upsert(int? id)
        {
            //IEnumerable<SelectListItem> CategoryDropDown = _db.Category.Select(i => new SelectListItem
            //{
            //    Text = i.Name,
            //    Value = i.Id.ToString()
            //});

            //ViewBag.CategoryDropDown = CategoryDropDown;

            //Product product = new Product();

            ProductVM productVM = new ProductVM()
            {
                Product = new Product(),

                CategorySelectList  = _db.Category.Select(i => new SelectListItem
                {
                    Text = i.Name,
                    Value = i.Id.ToString()
                })
            };

            if(id == null)
            {
                // for create
                return View(productVM);
            }
            else
            {
                productVM.Product = _db.Product.Find(id);

                if (productVM.Product == null)
                    NotFound();

                return View(productVM);
            }
        }

        // post - upsert
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Upsert(ProductVM obj)
        {
            if (ModelState.IsValid)
            {
                var files = HttpContext.Request.Form.Files;
                string webRootPath = _webHostEnvironment.WebRootPath;

                if(obj.Product.Id == 0)
                {
                    //Creating
                    string upload = webRootPath   WC.ImagePath;
                    string fileName = Guid.NewGuid().ToString();
                    string extention = Path.GetExtension(files[0].FileName);

                    using(var fileStream = new FileStream(Path.Combine(upload, fileName   extention), FileMode.Create))
                    {
                        files[0].CopyTo(fileStream);
                    }

                    obj.Product.Image = fileName   extention;

                    _db.Product.Add(obj.Product);
                }
                else
                {
                    //Updating
                }

                return RedirectToAction("Index");
            }
            return View();
        }
}

List of fields that participated in validation

enter image description here

From one answer, I realized that the Category field will remain null, and ef core will substitute the values. But I don't quite understand why so many fields are validated without being marked required in the model.

CodePudding user response:

By receives a POST action, ModelState takes all of the name-value pairs and adds them as individual instances of ModelStateEntry to an instance of ModelStateDictionary. ModelState checks all properties regardless of whether they have a Data annotations or not, such as you get a number, text, file etc. But for those data annotations you put on the properties the ModelState makes a special check based on it.

CodePudding user response:

Just the properties of the model you passed to controller would be validated,you could try custom model validation follow this document:

https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-6.0#custom-attributes

And you could try with ModelState.AddModelError(string.Empty, "errormessage");add model level error in backend.

  • Related