'How do I upload pdf into a folder and store the path into a database, and be able to view the uploaded file? Thank you

Here is my controller code

namespace MyClassWorkApplication.Areas.Admin.Controllers
{


    [Area("Admin")]
    [Authorize(Roles = "Admin")]
    public class ContentController : Controller
    {
        private readonly ApplicationDbContext _context;
        private IWebHostEnvironment _env;

        public ContentController(ApplicationDbContext context, IWebHostEnvironment env)
        {
            _context = context;
            _env = env;
        }

        // GET: Admin/Content/Create
        public IActionResult Create(int categoryItemId, int categoryId)
        {

            Content content = new Content
            {
                CategoryId = categoryId,
                CatItemId = categoryItemId
            };

            return View(content);
        }

        // POST: Admin/Content/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,Title,HTMLContent,VideoLink,CatItemId,CategoryId,PublicationPdfUrl")] Content content)
        {

            Profile profile = new Profile();
            profile.Title = content.Title;
            //loading remaining properties of the model from ViewModel

            //uploading file....
            string uniqueFileName = null;
            if (content.PublicationPdfUrl != null)
            {
                string folder = "Publications/pdf/";
                string serverFolder = Path.Combine(_env.WebRootPath, folder);
                uniqueFileName = Guid.NewGuid().ToString() + "_" + content.PublicationPdfUrl.FileName;
                string filePath = Path.Combine(serverFolder, uniqueFileName);
                content.PublicationPdfUrl.CopyTo(new FileStream(filePath, FileMode.Create));
                profile.PublicationPdfUrl = content.PublicationPdfUrl.FileName;

            }
            if (ModelState.IsValid)
            {
                content.CategoryItem = await _context.CategoryItem.FindAsync(content.CatItemId);
                _context.Add(content);
                await _context.SaveChangesAsync();

                return RedirectToAction(nameof(Index), "CategoryItem", new { categoryId = content.CategoryId });
            }
            return View(content);
        }



        // GET: Admin/Content/Edit/5
        public async Task<IActionResult> Edit(int categoryItemId, int categoryId)
        {
            if (categoryItemId == 0)
            {
                return NotFound();
            }

            var content = await _context.Content.SingleOrDefaultAsync(item => item.CategoryItem.Id == categoryItemId);

            content.CategoryId = categoryId;

            if (content == null)
            {
                return NotFound();
            }
            return View(content);
        }

        // POST: Admin/Content/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,Title,HTMLContent,VideoLink,CategoryId,PublicationPdfUrl")] Content content)
        {
            if (id != content.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(content);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!ContentExists(content.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index), "CategoryItem", new { categoryId = content.CategoryId });
            }
            return View(content);
        }


        private bool ContentExists(int id)
        {
            return _context.Content.Any(e => e.Id == id);
        }
    }
}

My Second Controller

namespace MyClassWorkApplication.Controllers
{
    public class ContentController : Controller
    {
        private readonly ApplicationDbContext _context;

        public ContentController(ApplicationDbContext context)
        {
            _context = context;
        }
        public async Task<IActionResult> Index(int categoryItemId)
        {
            Content content = await (from item in _context.Content
                                     where item.CategoryItem.Id == categoryItemId
                                     select new Content
                                     {
                                         Title = item.Title,
                                         VideoLink = item.VideoLink,
                                         HTMLContent = item.HTMLContent,
                                         PublicationPdfUrl = item.PublicationPdfUrl
                                     }).FirstOrDefaultAsync();

            return View(content);
        }
    }
}

This is my Model class (Content). It was reporting error with the IFormFile until I added the [NotMapped] attributes to it before the error disappears. However, It does not add the pdf Url into that database as I wanted.

public class Content
    {
        public int Id { get; set; }

        [Required]
        [StringLength(200, MinimumLength = 2)]
        public string Title { get; set; }

        [Display(Name = "HTML Content")]
        public string HTMLContent { get; set; }

        [Display(Name = "Video Link")]
        public string VideoLink { get; set; }

        public CategoryItem CategoryItem { get; set; }

        [NotMapped]
        public int CatItemId { get; set; }
        //Note: This property cannot be 
        //named CategoryItemId because this would
        //interfere with future migrations
        //It has been named like this
        //so as not to conflict with EF Core naming conventions

        [NotMapped]
        public int CategoryId { get; set; }

        [NotMapped]
        public IFormFile PublicationPdfUrl { get; set; }
    }

public class Profile
    {
        [Key]
        public int Id { get; set; }
        public string Title { get; set; }
        public string HTMLContent { get; set; }
        public string VideoLink { get; set; }
        public CategoryItem CategoryItem { get; set; }
        public int CatItemId { get; set; }
        public int CategoryId { get; set; }
        [Display(Name = "Upload your publication in pdf format")]

        public string PublicationPdfUrl { get; set; }
    }
}

This is my Create View

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>
<h4>Content</h4>
<hr />
<div class="row">
    <div class="col-md-10">
        <form method="post" enctype="multipart/form-data" asp-action="Create">
            <input type="hidden" asp-for="CategoryId">
            <input type="hidden" asp-for="CatItemId">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="HTMLContent" class="control-label"></label>
                <textarea asp-for="HTMLContent" row="10" class="form-control"></textarea>
                <span asp-validation-for="HTMLContent" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="VideoLink" class="control-label"></label>
                <input asp-for="VideoLink" class="form-control" />
                <span asp-validation-for="VideoLink" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="PublicationPdfUrl" class="control-label"></label>
                <div class="custom-file">
                    <input asp-for="PublicationPdfUrl" class="custom-file-input" id="customFile">
                    <label class="custom-file-label" for="customFile">Choose file...</label>
                </div>
                <span asp-validation-for="PublicationPdfUrl" class="text-danger"></span>
            </div>

            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary float-right" />
                <a asp-controller="CategoryItem" asp-action="Index" asp-route-categoryId="@Model.CategoryId" class="btn btn-outline-primary">Back to List</a>
            </div>
        </form>
    </div>
</div>

This is my Edit View

@{
    ViewData["Title"] = "Edit";
}

<h4>Edit</h4>

<h4>Content</h4>
<hr />
<div class="row">
    <div class="col-md-10">
        <form method="post" enctype="multipart/form-data" asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <input type="hidden" asp-for="CategoryId" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="HTMLContent" class="control-label"></label>
                <textarea asp-for="HTMLContent" row="10" class="form-control"></textarea>
                <span asp-validation-for="HTMLContent" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="VideoLink" class="control-label"></label>
                <input asp-for="VideoLink" class="form-control" />
                <span asp-validation-for="VideoLink" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="PublicationPdfUrl" class="control-label"></label>
                <div class="custom-file">
                    <input asp-for="PublicationPdfUrl" class="custom-file-input" id="customFile">
                    <label class="custom-file-label" for="customFile">Choose file...</label>
                </div>
                <span asp-validation-for="PublicationPdfUrl" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary float-right" />
                <a asp-controller="CategoryItem" asp-action="Index" asp-route-categoryId="@Model.CategoryId" class="btn btn-outline-primary">Back to List</a>
            </div>
        </form>
    </div>
</div>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source