The property is of an interface type ('IFormFile') MVC Core

半腔热情 提交于 2019-12-22 10:45:32

问题


I'm trying to make a form that i could save a file(image) , but it shows me an error:

InvalidOperationException: The property 'Product.Image' is of an interface type ('IFormFile'). If it is a navigation property manually configure the relationship for this property by casting it to a mapped entity type, otherwise ignore the property from the model. Apply

I dont know how to fix it , here's the code:

Product.cs

public class Product
    {
        public Product()
        {
            OrderDetails = new HashSet<OrderDetails>();
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int? CategoryId { get; set; }
        public decimal? Price { get; set; }
        public int? Quantity { get; set; }
        public string ImagePath { get; set; }

        public virtual ICollection<OrderDetails> OrderDetails { get; set; }
        public virtual Category Category { get; set; }
    }

ProductFormViewModel.cs

public class ProductFormViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int? CategoryId { get; set; }
        public decimal? Price { get; set; }
        public int? Quantity { get; set; }
        public IFormFile Image { get; set; }
    }

Create Action

  [HttpGet]
            public IActionResult Create()
            {
                var categories = _repository.GetCategories().ToList();
                var categoriesModel = categories.Select(p => new
                {
                    p.Id,
                    p.Name
                });

                ViewBag.Categories = new SelectList(categoriesModel, "Id", "Name");

                return View();
            }

[HttpPost]
        public IActionResult Create(ProductFormViewModel product)
        {

            var file = product.Image; // **it returns NULL**
            var upload = Path.Combine(_environment.ContentRootPath, "wwwroot\\uploads", product.Name);

            if (!Directory.Exists(upload))
                Directory.CreateDirectory(upload);

            var filePath = Path.Combine(upload, file.FileName);


            if (file.Length > 0)
            {
                using (var fileStream = new FileStream(filePath, FileMode.Create))
                {
                    file.CopyTo(fileStream);
                }
            }

            var producti = new Product();
            producti.CategoryId = product.CategoryId;
            producti.Description = product.Description;
            producti.Name = product.Name;
            producti.Price = product.Price;
            producti.Quantity = product.Quantity;
            producti.ImagePath = filePath;
            _repository.AddProduct(producti);
            _repository.SaveChanges();




            return RedirectToAction("Index","Products");
        }

Create.cshtml

@model ProductFormViewModel
<br />
<br />
<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
        </div>
        <div class="panel-body">
            <form class="form-group" asp-action="Create" asp-controller="Products" method="post">
                <input type="hidden" asp-for="Id"/>
                <div class="col-md-12">
                    <div class="form-group col-md-6">
                        <label asp-for="Name" class="control-label col-md-3"></label>
                        <input asp-for="Name" type="text" class="form-control col-md-3"/>
                    </div>
                    <div class="form-group col-md-6">
                        <label asp-for="CategoryId" class="control-label col-md-3"></label>
                        <select asp-for="CategoryId" asp-items="@ViewBag.Categories" class="form-control col-md-3">
                            <option  hidden disabled selected >Select One</option>
                        </select>
                    </div>
                    <div class="form-group col-md-6">
                        <label asp-for="Description" class="control-label col-md-3"></label>
                        <textarea asp-for="Description" class="form-control" rows="4"></textarea>

                    </div>
                    <div class="form-group col-md-6">

                        <label asp-for="Price" class="control-label col-md-3"></label>
                        <input type="text" asp-for="Price" class="form-control col-md-3"/>
                    </div>
                    <div class="form-group col-md-6">
                        <label asp-for="Quantity" class="control-label col-md-3"></label>
                        <input type="text" asp-for="Quantity" class="form-control col-md-3"/>
                    </div>
                    <div class="form-group col-md-12">
                        <label class="control-label">Select Image</label>
                        <input asp-for="Image" type="file" class="btn-file"/>
                    </div>
                    <div class="form-group col-md-12 text-center">
                        <input type="submit" class="btn btn-success" value="Save"/>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

回答1:


IFormFile is a type used by the ASP.NET Core framework and it does not have a sql server type equivalent.

For your domain model store it as byte[] and when you work with views, is ok for you to use the IFormFile type.

ProductModel:

public class Product
{
    public Product()
    {
        OrderDetails = new HashSet<OrderDetails>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public int? CategoryId { get; set; }
    public decimal? Price { get; set; }
    public int? Quantity { get; set; }
    public string ImagePath { get; set; }

    public virtual ICollection<OrderDetails> OrderDetails { get; set; }
    public virtual Category Category { get; set; }
}

ProductViewModel:

public class ProductViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public int? CategoryId { get; set; }
    public decimal? Price { get; set; }
    public int? Quantity { get; set; }
    public IFormFile Image { get; set; }
}

Controller method:

[HttpGet]
public IActionResult Create()
{
    var categories = _repository.GetCategories().ToList();
    var categoriesModel = categories.Select(p => new
    {
        p.Id,
        p.Name
    });

    ViewBag.Categories = new SelectList(categoriesModel, "Id", "Name");

    return View();
}

[HttpPost]
public IActionResult Create(ProductViewModel model)
{
    // Save the image to desired location and retrieve the path
    // string ImagePath = ...        

    // Add to db
    _repository.Add(new Product
    {
        Id = model.Id,
        ImagePath = ImagePath,
        // and so on
    });

    return View();
}

Also specify to the form enctype="multipart/form-data" in your view.



来源:https://stackoverflow.com/questions/43161458/the-property-is-of-an-interface-type-iformfile-mvc-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!