uploading image Asp.net core 3.1 with postgresql - c#

I'm trying to upload a image in asp .NET core. I could not upload the image.
There is no error message. all are work correctly without uploading the image.
anyone tell me what is problem in these codes
also I have a folder "Uploads" in the wwwroot folder.
I attach my codes below.
This is my Create.cshtml
#model WebApplication1.ViewModels.EmployeeViewModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Employee</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data ">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="EmployeeName" class="control-label"></label>
<input asp-for="EmployeeName" class="form-control" />
<span asp-validation-for="EmployeeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmployeeProfile" class="control-label"></label>
<div class="custom-file">
<input type="file" asp-for="EmployeeProfile" class="custom-file-input" />
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
<span asp-validation-for="EmployeeProfile" class="text-danger"></span>
#*<label asp-for="EmployeeImage" class="control-label"></label>
<input asp-for="EmployeeImage" class="form-control" />
<span asp-validation-for="EmployeeImage" class="text-danger"></span>*#
</div>
<div class="form-group">
<label asp-for="DepartmentId" class="control-label"></label>
<select asp-for="DepartmentId" class="form-control" asp-items="ViewBag.DepartmentId"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-sm btn-primary rounded-0" />
<a asp-action="Index" class="btn btn-sm btn-primary rounded-0">Back to List</a>
#*<a asp-action="Index">Back to List</a>*#
</div>
</form>
</div>
</div>
#section Scripts {
<script>
// Add the following code if you want the name of the file appear on select
$(".custom-file-input").on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
});
</script>
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
this is my EmployeesController
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WebApplication1.Models;
using WebApplication1.ViewModels;
namespace WebApplication1.Controllers
{
public class EmployeesController : Controller
{
private readonly EmployeeDbContext _context;
private readonly IWebHostEnvironment webHostEnvironment;
public EmployeesController(EmployeeDbContext context, IWebHostEnvironment hostEnvironment)
{
_context = context;
webHostEnvironment = hostEnvironment;
}
// GET: Employees
//public async Task<IActionResult> Index()
//{
// var employeeDbContext = _context.Employees.Include(e => e.Department);
// return View(await employeeDbContext.ToListAsync());
//}
public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? pageNumber)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}
//var employeeDbContext = _context.Employees.Include(e => e.Department);
ViewData["CurrentFilter"] = searchString;
var employee = from em in _context.Employees.Include(e => e.Department)
select em;
// var employee = from e in _context.Employees
if (!String.IsNullOrEmpty(searchString))
{
employee = employee.Where(em => em.EmployeeName.Contains(searchString)
|| em.EmployeeName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
employee = employee.OrderByDescending(em => em.EmployeeName);
break;
default:
employee = employee.OrderBy(em => em.EmployeeName);
break;
}
int pageSize = 3;
return View(await PaginatedList<Employee>.CreateAsync(employee.AsNoTracking(), pageNumber ?? 1, pageSize));
//return View(await _context.Departments.ToListAsync());
}
// GET: Employees/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees
.Include(e => e.Department)
.FirstOrDefaultAsync(m => m.Id == id);
var EmployeeViewModel = new EmployeeViewModel()
{
Id = employee.Id,
EmployeeName = employee.EmployeeName,
DepartmentId = employee.DepartmentId,
ExistingImage = employee.EmployeeImage
};
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// GET: Employees/Create
public IActionResult Create()
{
ViewData["DepartmentId"] = new SelectList(_context.Departments, "Id", "departmentName");
return View();
}
// POST: Employees/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("EmployeeName,EmployeeImage,DepartmentId")] EmployeeViewModel model)
{
if (ModelState.IsValid)
{
string uniqueFileName = ProcessUploadedFile(model);
Employee employee = new Employee
{
EmployeeName = model.EmployeeName,
DepartmentId = model.DepartmentId,
EmployeeImage = uniqueFileName
};
_context.Add(employee);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["DepartmentId"] = new SelectList(_context.Departments, "Id", "departmentName", model.DepartmentId);
return View(model);
}
// GET: Employees/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees.FindAsync(id);
var EmployeeViewModel = new EmployeeViewModel()
{
Id = employee.Id,
EmployeeName = employee.EmployeeName,
DepartmentId = employee.DepartmentId,
ExistingImage = employee.EmployeeImage
}; if (employee == null)
{
return NotFound();
}
ViewData["DepartmentId"] = new SelectList(_context.Departments, "Id", "departmentName", employee.DepartmentId);
return View(EmployeeViewModel);
}
// POST: Employees/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,EmployeeName,EmployeeImage,DepartmentId")] EmployeeViewModel model)
{
if (id != model.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
var employee = await _context.Employees.FindAsync(model.Id);
employee.EmployeeName = model.EmployeeName;
employee.DepartmentId = model.DepartmentId;
if (model.EmployeeProfile != null)
{
if (model.ExistingImage != null)
{
string filePath = Path.Combine(webHostEnvironment.WebRootPath, "Uploads", model.ExistingImage);
System.IO.File.Delete(filePath);
}
employee.EmployeeImage = ProcessUploadedFile(model);
}
_context.Update(employee);
await _context.SaveChangesAsync();
//try
//{
// _context.Update(model);
// await _context.SaveChangesAsync();
//}
//catch (DbUpdateConcurrencyException)
//{
// if (!EmployeeExists(model.Id))
// {
// return NotFound();
// }
// else
// {
// throw;
// }
//}
return RedirectToAction(nameof(Index));
}
ViewData["DepartmentId"] = new SelectList(_context.Departments, "Id", "departmentName", model.DepartmentId);
return View();
}
// GET: Employees/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees
.Include(e => e.Department)
.FirstOrDefaultAsync(m => m.Id == id);
var EmployeeViewModel = new EmployeeViewModel()
{
Id = employee.Id,
EmployeeName = employee.EmployeeName,
DepartmentId = employee.DepartmentId,
ExistingImage = employee.EmployeeImage
};
if (employee == null)
{
return NotFound();
}
return View(EmployeeViewModel);
}
// POST: Employees/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var employee = await _context.Employees.FindAsync(id);
var CurrentImage = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\Uploads", employee.EmployeeImage);
_context.Employees.Remove(employee);
if (await _context.SaveChangesAsync() > 0)
{
if (System.IO.File.Exists(CurrentImage))
{
System.IO.File.Delete(CurrentImage);
}
}
return RedirectToAction(nameof(Index));
}
private bool EmployeeExists(int id)
{
return _context.Employees.Any(e => e.Id == id);
}
private string ProcessUploadedFile(EmployeeViewModel model)
{
string uniqueFileName = null;
if (model.EmployeeProfile != null)
{
string uploadsFolder = Path.Combine(webHostEnvironment.WebRootPath, "Uploads");
// uniqueFileName = Guid.NewGuid().ToString() + "_" + model.EmployeeProfile.FileName;
uniqueFileName = Guid.NewGuid().ToString() + "_" + Path.GetFileName(model.EmployeeProfile.FileName);
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
model.EmployeeProfile.CopyTo(fileStream);
}
}
return uniqueFileName;
}
}
}
This is ProcessUploadedFile method
private string ProcessUploadedFile(EmployeeViewModel model)
{
string uniqueFileName = null;
if (model.EmployeeProfile != null)
{
string uploadsFolder = Path.Combine(webHostEnvironment.WebRootPath, "Uploads");
// uniqueFileName = Guid.NewGuid().ToString() + "_" + model.EmployeeProfile.FileName;
uniqueFileName = Guid.NewGuid().ToString() + "_" + Path.GetFileName(model.EmployeeProfile.FileName);
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
model.EmployeeProfile.CopyTo(fileStream);
}
}
return uniqueFileName;
}
i have 3 viewmodels, see below
EmployeeViewModel
EditImageViewModel
UploadImageViewModel
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using WebApplication1.Models;
using WebApplication1.ViewModels;
namespace WebApplication1.ViewModels
{
public class EmployeeViewModel : EditImageViewModel
{
[Required(ErrorMessage = "Please enter Employee Name")]
public string EmployeeName { get; set; }
// Navigation Properties
public int? DepartmentId { get; set; }
public Department Department { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1.ViewModels
{
public class EditImageViewModel : UploadImageViewModel
{
public int Id { get; set; }
public string ExistingImage { get; set; }
}
}
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1.ViewModels
{
public class UploadImageViewModel
{
[Required(ErrorMessage = "Please choose profile image")]
[Display(Name = "Profile Picture")]
public IFormFile EmployeeProfile { get; set; }
}
}

You have commented out the EmployeeImage, you only passed the EmployeeProfile to action, but
you didn't bind the EmployeeProfile.
Change to this:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("EmployeeName,EmployeeProfile,//***others")] EmployeeViewModel model)
Then I can upload the file using your code.
The [Bind] specifies which properties of a model should be included in model binding.Check:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-5.0#bind-attribute
whole code:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("EmployeeName,EmployeeProfile")] EmployeeViewModel model)
{
if (ModelState.IsValid)
{
string uniqueFileName = ProcessUploadedFile(model);
Employee employee = new Employee
{
EmployeeName = model.EmployeeName,
EmployeeImage = uniqueFileName
};
_context.Add(employee);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return RedirectToAction("Index");
}
private string ProcessUploadedFile(EmployeeViewModel model)
{
string uniqueFileName = null;
if (model.EmployeeProfile != null)
{
string uploadsFolder = Path.Combine(webHostEnvironment.WebRootPath, "Uploads");
// uniqueFileName = Guid.NewGuid().ToString() + "_" + model.EmployeeProfile.FileName;
uniqueFileName = Guid.NewGuid().ToString() + "_" + Path.GetFileName(model.EmployeeProfile.FileName);
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
model.EmployeeProfile.CopyTo(fileStream);
}
}
return uniqueFileName;
}
Create.cshtml:
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="EmployeeName" class="control-label"></label>
<input asp-for="EmployeeName" class="form-control" />
<span asp-validation-for="EmployeeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmployeeProfile" class="control-label"></label>
<div class="custom-file">
<input type="file" asp-for="EmployeeProfile" class="custom-file-input" />
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
<span asp-validation-for="EmployeeProfile" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-sm btn-primary rounded-0" />
<a asp-action="Index" class="btn btn-sm btn-primary rounded-0">Back to List</a>
</div>
</form>
</div>
Model:
public class Employee
{
[Key]
public int Id { get; set; }
public string EmployeeName { get; set; }
public string EmployeeImage { get; set; }
}
public class EmployeeViewModel
{
public int Id { get; set; }
public string EmployeeName { get; set; }
public string LastName { get; set; }
[NotMapped]
public IFormFile EmployeeProfile { get; set; }
}
Result:

Related

ASP.net mvc create a new data does not work

when i try to create a new data from the form and i do not get any error and the page just refresh , without creating any new data . im using sql server and i have a ForeignKey from another table.
my course controller:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using SchoolGrades.Models;
namespace SchoolGrades.Controllers { public class CoursesController : Controller { private readonly UniDBContext _context;
public CoursesController(UniDBContext context)
{
_context = context;
}
// GET: Courses
public async Task<IActionResult> Index()
{
var uniDBContext = _context.Courses.Include(c => c.ProfessorsAfmNavigation);
return View(await uniDBContext.ToListAsync());
}
// GET: Courses/Details/5
public async Task<IActionResult> Details(string id)
{
if (id == null || _context.Courses == null)
{
return NotFound();
}
var course = await _context.Courses
.Include(c => c.ProfessorsAfmNavigation)
.FirstOrDefaultAsync(m => m.IdCourse == id);
if (course == null)
{
return NotFound();
}
return View(course);
}
// GET: Courses/Create
public IActionResult Create()
{
ViewData["ProfessorsAfm"] = new SelectList(_context.Professors, "Afm", "Afm");
return View();
}
// POST: Courses/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("IdCourse,CourseTitle,CourseSemester,ProfessorsAfm")] Course course)
{
if (ModelState.IsValid)
{
_context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["ProfessorsAfm"] = new SelectList(_context.Professors, "Afm", "Afm", course.ProfessorsAfm);
return View(course);
}
// GET: Courses/Edit/5
public async Task<IActionResult> Edit(string id)
{
if (id == null || _context.Courses == null)
{
return NotFound();
}
var course = await _context.Courses.FindAsync(id);
if (course == null)
{
return NotFound();
}
ViewData["ProfessorsAfm"] = new SelectList(_context.Professors, "Afm", "Afm", course.ProfessorsAfm);
return View(course);
}
// POST: Courses/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("IdCourse,CourseTitle,CourseSemester,ProfessorsAfm")] Course course)
{
if (id != course.IdCourse)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(course);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CourseExists(course.IdCourse))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["ProfessorsAfm"] = new SelectList(_context.Professors, "Afm", "Afm", course.ProfessorsAfm);
return View(course);
}
// GET: Courses/Delete/5
public async Task<IActionResult> Delete(string id)
{
if (id == null || _context.Courses == null)
{
return NotFound();
}
var course = await _context.Courses
.Include(c => c.ProfessorsAfmNavigation)
.FirstOrDefaultAsync(m => m.IdCourse == id);
if (course == null)
{
return NotFound();
}
return View(course);
}
// POST: Courses/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(string id)
{
if (_context.Courses == null)
{
return Problem("Entity set 'UniDBContext.Courses' is null.");
}
var course = await _context.Courses.FindAsync(id);
if (course != null)
{
_context.Courses.Remove(course);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool CourseExists(string id)
{
return (_context.Courses?.Any(e => e.IdCourse == id)).GetValueOrDefault();
}
}
}
`
my course model:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore;
namespace SchoolGrades.Models;
[Table("course")] public partial class Course { [Key] [Column("idCOURSE")] [StringLength(25)] [Unicode(false)] public string IdCourse { get; set; } = null!;
[StringLength(60)]
[Unicode(false)]
public string CourseTitle { get; set; } = null!;
[StringLength(25)]
[Unicode(false)]
public string CourseSemester { get; set; } = null!;
[Column("PROFESSORS_AFM")]
[StringLength(25)]
[Unicode(false)]
public string ProfessorsAfm { get; set; } = null!;
[InverseProperty("CourseIdCourseNavigation")]
public virtual CourseHasStudent? CourseHasStudent { get; set; }
[ForeignKey("ProfessorsAfm")]
[InverseProperty("Courses")]
public virtual Professor ProfessorsAfmNavigation { get; set; } = null!;
}
and course create view :
#model SchoolGrades.Models.Course
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="IdCourse" class="control-label"></label>
<input asp-for="IdCourse" class="form-control" />
<span asp-validation-for="IdCourse" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CourseTitle" class="control-label"></label>
<input asp-for="CourseTitle" class="form-control" />
<span asp-validation-for="CourseTitle" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CourseSemester" class="control-label"></label>
<input asp-for="CourseSemester" class="form-control" />
<span asp-validation-for="CourseSemester" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ProfessorsAfm" class="control-label"></label>
<select asp-for="ProfessorsAfm" class ="form-control" asp-items="ViewBag.ProfessorsAfm"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
i removed the if statement from the course controller .
if (ModelState.IsValid)
{ _context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
and i kept it like this and it worked and i could create a new data in the table after i removed the if statement .
_context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
any other solutions please.

Select multiple and display corresponding value from another model

I have Two different ASP.net Core 6.0 applications running that have tables linked to other tables by foreign keys. I create a CRUD for both pages. At the first CRUD (PriceList) page, I will enter the data. At the the second CRUD (CombineStage) of the page I will get the data (Stage) from the first page (Pricelist) using multiple select and the search box and its corresponding price in the Index page after using multiple select. I can't find any code commands to make this work. Any help would be appreciated. My foreign key is PricelistId. Below is my code:
CombineStage.cs
using System.ComponentModel.DataAnnotations;
namespace WebApp.Models
{
public class CombineStage
{
[Key]
public int StageId { get; set; }
[Required(ErrorMessage = "Bạn chưa nhập tên công đoạn")]
public string Name { get; set; }
[Required(ErrorMessage = "Bạn chưa chọn công đoạn")]
public int PricelistId { get; set; }
[Required(ErrorMessage = "Bạn chưa chọn ảnh")]
public string Picture { get; set; }
[Required(ErrorMessage = "Bạn chưa nhập giá tiền")]
public int Price { get; set; }
public virtual PriceList PriceList { get; set; }
}
}
CombineStagesController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WebApp.Models;
namespace WebApp.Areas.Admin.Controllers
{
[Area("Admin")]
public class CombineStagesController : Controller
{
private readonly ManageContext _context;
public CombineStagesController(ManageContext context)
{
_context = context;
}
// GET: Admin/CombineStages
public async Task<IActionResult> Index()
{
var manageContext = _context.CombineStage.Include(c => c.PriceList);
return View(await manageContext.ToListAsync());
}
// GET: Admin/CombineStages/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null || _context.CombineStage == null)
{
return NotFound();
}
var combineStage = await _context.CombineStage
.Include(c => c.PriceList)
.FirstOrDefaultAsync(m => m.StageId == id);
if (combineStage == null)
{
return NotFound();
}
return View(combineStage);
}
// GET: Admin/CombineStages/Create
public IActionResult Create()
{
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage");
return View();
}
// POST: Admin/CombineStages/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage)
{
if (ModelState.IsValid)
{
_context.Add(combineStage);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage", combineStage.PricelistId);
return View(combineStage);
}
// GET: Admin/CombineStages/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null || _context.CombineStage == null)
{
return NotFound();
}
var combineStage = await _context.CombineStage.FindAsync(id);
if (combineStage == null)
{
return NotFound();
}
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage", combineStage.PricelistId);
return View(combineStage);
}
// POST: Admin/CombineStages/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage)
{
if (id != combineStage.StageId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(combineStage);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CombineStageExists(combineStage.StageId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage", combineStage.PricelistId);
return View(combineStage);
}
// GET: Admin/CombineStages/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null || _context.CombineStage == null)
{
return NotFound();
}
var combineStage = await _context.CombineStage
.Include(c => c.PriceList)
.FirstOrDefaultAsync(m => m.StageId == id);
if (combineStage == null)
{
return NotFound();
}
return View(combineStage);
}
// POST: Admin/CombineStages/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
if (_context.CombineStage == null)
{
return Problem("Entity set 'ManageContext.CombineStage' is null.");
}
var combineStage = await _context.CombineStage.FindAsync(id);
if (combineStage != null)
{
_context.CombineStage.Remove(combineStage);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool CombineStageExists(int id)
{
return _context.CombineStage.Any(e => e.StageId == id);
}
}
}
Create
#model WebApp.Models.CombineStage
#{
ViewData["Title"] = "Create";
Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
}
<h1>Create</h1>
<h4>CombineStage</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PricelistId" class="control-label"></label>
<select asp-for="PricelistId" class ="form-control" asp-items="ViewBag.PricelistId" multiple>
</select>
</div>
<div class="form-group">
<label asp-for="Picture" class="control-label"></label>
<input asp-for="Picture" class="form-control" />
<span asp-validation-for="Picture" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
Thank you so much!
Update Pricelist:
Pricelist.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
namespace WebApp.Models
{
public partial class PriceList
{
public PriceList()
{
StageDetails = new HashSet<StageDetail>();
CombineStages = new HashSet<CombineStage>();
}
[Key]
public int PricelistId { get; set; }
[Required(ErrorMessage = "Bạn chưa chọn ảnh")]
public string Image { get; set; }
[Required (ErrorMessage = "Bạn chưa chọn máy may")]
public Machine Machine { get; set; }
[Required (ErrorMessage = "Bạn chưa tên nhập công đoạn")]
public string Stage { get; set; }
[Required (ErrorMessage = "Bạn chưa nhập giá tiền")]
public int Price { get; set; }
public virtual ICollection<StageDetail> StageDetails { get; set; }
public virtual ICollection<CombineStage> CombineStages { get; set; }
}
public enum Machine
{
VS,
[Display(Name = "1K")]
OneK
}
}
PriceListsController
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WebApp.Models;
using WebApp.ViewModel;
namespace WebApp.Areas.Admin.Controllers
{
[Area("Admin")]
public class PriceListsController : Controller
{
private readonly ManageContext _context;
private readonly IWebHostEnvironment _environment;
public PriceListsController(ManageContext context, IWebHostEnvironment environment)
{
_context = context;
_environment = environment;
}
public async Task<IActionResult> Index()
{
return View(await _context.PriceLists.ToListAsync());
}
public async Task<IActionResult> Details(int? id)
{
try
{
if (id == null)
{
return NotFound();
}
var priceList = await _context.PriceLists
.FirstOrDefaultAsync(m => m.PricelistId == id);
var priceListModelView = new PriceListViewModel()
{
Id = priceList.PricelistId,
ExistingImage = priceList.Image,
Machine = priceList.Machine,
Stage = priceList.Stage,
Price = priceList.Price
};
if (priceList == null)
{
return NotFound();
}
return View(priceList);
}
catch (Exception)
{
throw;
}
}
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(PriceListViewModel model)
{
try
{
if (ModelState.IsValid)
{
string uniqueFileName = ProcessUploadedFile(model);
PriceList priceList = new()
{
Image = uniqueFileName,
Machine = model.Machine,
Stage = model.Stage,
Price = model.Price
};
_context.Add(priceList);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (Exception)
{
throw;
}
return View(model);
}
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var priceList = await _context.PriceLists.FindAsync(id);
var priceListViewModel = new PriceListViewModel()
{
Id = priceList.PricelistId,
ExistingImage = priceList.Image,
Machine = priceList.Machine,
Stage = priceList.Stage,
Price = priceList.Price
};
if (priceList == null)
{
return NotFound();
}
return View(priceListViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, PriceListViewModel model)
{
if (ModelState.IsValid)
{
var priceList = await _context.PriceLists.FindAsync(model.Id);
priceList.Machine = model.Machine;
priceList.Stage = model.Stage;
priceList.Price = model.Price;
if (model.PricelistImage != null)
{
if (model.ExistingImage != null)
{
string filePath = Path.Combine(_environment.WebRootPath, "Images", model.ExistingImage);
System.IO.File.Delete(filePath);
}
priceList.Image = ProcessUploadedFile(model);
}
_context.Update(priceList);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View();
}
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var priceList = await _context.PriceLists
.FirstOrDefaultAsync(m => m.PricelistId == id);
var priceListViewModel = new PriceListViewModel()
{
Id = priceList.PricelistId,
ExistingImage = priceList.Image,
Machine = priceList.Machine,
Stage = priceList.Stage,
Price = priceList.Price
};
if (priceList == null)
{
return NotFound();
}
return View(priceListViewModel);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var priceList = await _context.PriceLists.FindAsync(id);
//string deleteFileFromFolder = "wwwroot\\Uploads\\";
string deleteFileFromFolder = Path.Combine(_environment.WebRootPath, "Images");
var CurrentImage = Path.Combine(Directory.GetCurrentDirectory(), deleteFileFromFolder, priceList.Image);
_context.PriceLists.Remove(priceList);
if (System.IO.File.Exists(CurrentImage))
{
System.IO.File.Delete(CurrentImage);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool SpeakerExists(int id)
{
return _context.PriceLists.Any(e => e.PricelistId == id);
}
private string ProcessUploadedFile(PriceListViewModel model)
{
string uniqueFileName = null;
string path = Path.Combine(_environment.WebRootPath, "Images");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (model.PricelistImage != null)
{
string uploadsFolder = Path.Combine(_environment.WebRootPath, "Images");
uniqueFileName = Guid.NewGuid().ToString() + "_" + model.PricelistImage.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
model.PricelistImage.CopyTo(fileStream);
}
}
return uniqueFileName;
}
}
}
Update Create(HTTPPost) CombineStagesController:
(But it still hasn't solved my request. I want when I select multiple then I get the entire corresponding Price value in Index Page)
public IActionResult Create()
{
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage, int[] PricelistId)
{
foreach (var id in PricelistId)
{
var stage = _context.PriceLists.Where(m => m.PricelistId == id).Select(x => x.Stage).ToString();
}
if (ModelState.IsValid)
{
_context.Add(combineStage);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(combineStage);
}
Update
Things I'm looking forward to
Next I will choose 2 option stages that I created
Next step, I want the total price of the 2 process options I have selected here
Finally, I want to show all the stages and prices of my 2 options that I have selected
That's all my request.
It's not entirely clear what you're expected result is with regard to records and their respective prices, but the binding code in your Create(CombinedStage, int[]) appears problematic given the PricelistId binding to CombinedStage. I would suggest creating a view model that reflects the form elements with an array/collection of simple values for PriceListIds in order for <select multiple>. For example, the new CombinedStageViewModel posted to the Create should have a property for `PricelistIds' such as the following for :
public IEnumerable<int> PricelistIds { get; set; }
Again, it's not entirely clear from the provided sample code or the accompanying description of the problem what the desired behavior is with respect to getting "...the entire corresponding Price value in Index Page." If you can post a sample project and define the expected results, it would make it much easier to provide a comprehensive answer to your question.
I made a simple test, you can refer to it.
I added a field to CombineStage to store your options:
public class CombineStage
{
[Key]
[ForeignKey("StageId")]
public int StageId { get; set; }
[Required(ErrorMessage = "Bạn chưa nhập tên công đoạn")]
public string Name { get; set; }
[Required(ErrorMessage = "Bạn chưa chọn công đoạn")]
[ForeignKey("PricelistId")]
public int PricelistId { get; set; }
[Required(ErrorMessage = "Bạn chưa chọn ảnh")]
public string Picture { get; set; }
[Required(ErrorMessage = "Bạn chưa nhập giá tiền")]
public int Price { get; set; }
public string PricelistIdList { get; set; }
public virtual PriceList PriceList { get; set; }
}
CombineStagesController:
public class CombineStagesController : Controller
{
private readonly ManageContext _context;
public CombineStagesController(ManageContext context)
{
_context = context;
}
// GET: Admin/CombineStages
public async Task<IActionResult> Index()
{
var manageContext = _context.CombineStage.Include(c => c.PriceList);
return View(await manageContext.ToListAsync());
}
// GET: Admin/CombineStages/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null || _context.CombineStage == null)
{
return NotFound();
}
var combineStage = await _context.CombineStage
.Include(c => c.PriceList)
.FirstOrDefaultAsync(m => m.StageId == id);
int[] PriceIdList = combineStage.PricelistIdList.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
List<PriceList> priceLists = new List<PriceList>();
foreach(var PriceId in PriceIdList)
{
var PriceDetails = _context.PriceLists.Where(c => c.PricelistId == PriceId).FirstOrDefault();
priceLists.Add(PriceDetails);
}
ViewBag.priceLists = priceLists;
if (combineStage == null)
{
return NotFound();
}
return View(combineStage);
}
// GET: Admin/CombineStages/Create
public IActionResult Create()
{
var priceLists = _context.PriceLists.ToList();
List<SelectListItem> mylist = new List<SelectListItem>();
foreach (var price in priceLists)
{
mylist.Add(new SelectListItem { Text = price.Stage, Value = price.PricelistId.ToString() });
}
ViewBag.PricelistId = mylist;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Name,PricelistId,Picture,Price,PriceList")] CombineStage combineStage, int[] PricelistId)
{
int price = 0;
var stage = "";
PriceList priceList = new PriceList();
foreach (var id in PricelistId)
{
stage = _context.PriceLists.Where(m => m.PricelistId == id).FirstOrDefault().Stage.ToString();
price += _context.PriceLists.Where(m => m.PricelistId == id).FirstOrDefault().Price;
priceList = _context.PriceLists.Where(m => m.PricelistId == id).FirstOrDefault();
}
combineStage.Price = price;
combineStage.PriceList = priceList;
combineStage.PricelistIdList = string.Join(",", PricelistId);
ModelState.Clear();
if (TryValidateModel(combineStage))
{
_context.Add(combineStage);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(combineStage);
}
}
Create.cshtml:
#model _2022092602.Models.CombineStage
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>CombineStage</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PricelistId" class="control-label"></label>
<select asp-for="PricelistId" class ="form-control" asp-items="#ViewBag.PricelistId" multiple>
</select>
</div>
<div class="form-group">
<label asp-for="Picture" class="control-label"></label>
<input asp-for="Picture" class="form-control" />
<span asp-validation-for="Picture" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
Details.cshtml:
#model _2022092602.Models.CombineStage
<div>#Model.Name</div>
<div>#Model.Picture</div>
<div>#Model.Price</div>
<div>
#foreach (var price in ViewBag.priceLists)
{
<div>
<span>#price.PricelistId</span>
<span>#price.Price</span>
<span>#price.Stage</span>
</div>
}
</div>
Test Result:

Pass list item wih viewmodel in .net core

I'm new to this and this might be quite easy for some people.
I'm struggling to connect a particular field (dropdown list item) between a View and a Controller. What I'm pretending is to associate a category (from a list) to a product.
For this particular Controller, my system as a Model, a Service and a ViewModel.
For the product class I have the following code:
public class DryGoodsProduct
{
public int Id { get; set; }
public string ProductName { get; set; }
[Display(Name = "Category")]
[Required]
public DryGoodsCategory DryGoodsCategory { get; set; }
public int DryGoodsCategoryId { get; set; }
public DryGoodsProduct()
{ }
public DryGoodsProduct(int id, string productName, DryGoodsCategory category)
{
Id = id;
ProductName = productName;
DryGoodsCategory = category;
}
}
The category class is the following:
public class DryGoodsCategory
{
public int Id { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
public virtual ICollection<DryGoodsProduct> DryGoodsProducts { get; set; }
public DryGoodsCategory()
{
}
public DryGoodsCategory(int id, string categoryName)
{
Id = id;
CategoryName = categoryName;
}
}
The product service class is the following:
public class DryGoodsProductService
{
private readonly DB _context;
public DryGoodsProductService(DB context)
{
_context = context;
}
public async Task<List<DryGoodsProduct>> FindAllAsync()
{
return await _context.DryGoodsProducts
.Include(obj => obj.DryGoodsCategory)
.ToListAsync();
}
public async Task InsertAsync(DryGoodsProduct drygoodsProduct)
{
_context.Add(drygoodsProduct);
await _context.SaveChangesAsync();
}
public async Task<DryGoodsProduct> FindByIdAsync(int id)
{
return await _context.DryGoodsProducts
.Include(obj => obj.DryGoodsCategory)
.FirstOrDefaultAsync(x => x.Id == id);
}
public async Task RemoveAsync(int id)
{
try
{
var obj = await _context.DryGoodsProducts.FindAsync(id);
_context.DryGoodsProducts.Remove(obj);
await _context.SaveChangesAsync();
}
catch (IntegrityException e)
{
throw new IntegrityException(e.Message);
}
}
public async Task UpdateAsync(DryGoodsProduct drygoodsProduct)
{
bool hasAny = await _context.DryGoodsProducts.AnyAsync(x => x.Id == drygoodsProduct.Id);
if (!hasAny)
{
throw new NotFoundException("ID não encontrado");
}
try
{
_context.Update(drygoodsProduct);
await _context.SaveChangesAsync();
}
catch (DbConcurrencyException ex)
{
throw new DbConcurrencyException(ex.Message);
}
}
}
and the view model class is:
public class DryGoodsProductViewModel
{
public DryGoodsProduct drygoodsProduct { get; set; }
public virtual ICollection<DryGoodsCategory> DryGoodsCategories { get; set; }
}
the controller is the following:
public async Task<IActionResult> Create()
{
var categories = await _categoryService.FindAllAsync();
var product = new DryGoodsProduct();
var viewmodel = new DryGoodsProductViewModel()
{
drygoodsProduct = product,
DryGoodsCategories = categories,
};
return View(viewmodel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(DryGoodsProduct product)
{
if (ModelState.IsValid)
{
await _productService.InsertAsync(product);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(product);
}
and the create view :
enter #model Library.ViewModels.Logistics.DryGoodsProductViewModel
#{
ViewData["Title"] = "Create";
Layout = "~/Areas/Logistics/Views/Shared/_LogisticsLayout.cshtml"; }
<h1>Create</h1>
<h4>Products</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
#Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="drygoodsProduct.ProductName" class="control-label"></label>
<input asp-for="drygoodsProduct.ProductName" class="form-control" />
<span asp-validation-for="drygoodsProduct.ProductName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="drygoodsProduct.DryGoodsCategoryId" class="control-label"></label>
<select asp-for="drygoodsProduct.DryGoodsCategoryId" asp-items="#(new SelectList(Model.DryGoodsCategories, "Id", "CategoryName"))" class="form-control"></select>
<span asp-validation-for="drygoodsProduct.DryGoodsCategoryId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
So...
The error says:
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the
ViewDataDictionary is of type
'Library.Models.Logistics.DryGoods.DryGoodsProduct', but this
ViewDataDictionary instance requires a model item of type
'Library.ViewModels.Logistics.DryGoodsProductViewModel'.
I mean, I've done something quit similar with another controller and everything is ok.
I would appreciate some feedback on how to solve this.

ASP.NET Web App CORE: the HttpPost Edit Method in Controller not being called

When i redirect to the Edit.cshtml page, only the HttpGet seems to be working. The HttpPost is not working. Which means that when I make changes and click on the Edit button on the Edit form, the HttpPost Edit is supposed to be invoked to call the PUT API. But the HttpGet Edit is called instead... What have I done wrong?
The HttpGet to retrieve the existing info
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
await ViewBags();
HttpResponseMessage response = await GlobalVariables.WebApiClient.GetAsync("article/detail/" + id.ToString());
if (response.IsSuccessStatusCode)
{
var authorTagArticle = new AuthorTagArticle();
authorTagArticle = response.Content.ReadAsAsync<AuthorTagArticle>().Result;
var articleForm = new ArticleForm();
articleForm.ArticleId = authorTagArticle.Article.ArticleId;
articleForm.ArticleTitle = authorTagArticle.Article.ArticleTitle;
articleForm.ArticleContent = authorTagArticle.Article.ArticleContent;
articleForm.CreatedOn = authorTagArticle.Article.CreatedOn;
articleForm.ImagePath = authorTagArticle.Article.ImagePath;
articleForm.AuthorIds = authorTagArticle.Author.Select(e => e.UserId).ToArray();
articleForm.TagIds = authorTagArticle.Tag.Select(e => e.TagId).ToArray();
return View(articleForm);
}
else
{
TempData["error"] = "Error - Unable to open Edit Article Menu";
return RedirectToAction("Index", "Home");
}
}
The HttpPost Edit method: to call the PUT API
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, ArticleForm articleForm)
{
if (id != articleForm.ArticleId)
{
return NotFound();
}
//If Image is Updated
var content = Request.Form.Files;
const long MaxLength = 10485760; // 10MB
string oldImagePath = articleForm.ImagePath;
if (content.Count() > 0 && content.First().ContentType.Contains("image") && content.First().Length < MaxLength)
{
articleForm.ImagePath = "article/" + content.First().FileName;
}
else
{
ModelState.AddModelError("Image", "Please select a valid image less than 10MB");
}
if (ModelState.IsValid)
{
try
{
Article article = new Article();
article.ArticleId = articleForm.ArticleId;
article.ArticleTitle = articleForm.ArticleTitle;
article.ArticleContent = articleForm.ArticleContent;
article.CreatedOn = articleForm.CreatedOn;
article.ImagePath = articleForm.ImagePath;
HttpResponseMessage response = await GlobalVariables.WebApiClient.PutAsJsonAsync("article/edit/" + id, article);
if (response.IsSuccessStatusCode)
{
TempData["success"] = "Article Updated!";
return RedirectToAction("Index", "Article");
}
else
{
TempData["error"] = "Error - Unable to edit article!";
return RedirectToAction("Index", "Home");
}
}
catch (DbUpdateConcurrencyException) { }
}
return View(articleForm);
}
Edit.cshtml
#model SCANews_UI.Models.ArticleForm
#{ ViewData["Title"] = "Edit"; }
<h1>Edit Article</h1>
<div class="card" style="width: 70rem;">
<div class="card-body">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ArticleId" />
<div class="form-group">
<label asp-for="ArticleTitle" class="control-label"></label>
<input asp-for="ArticleTitle" class="form-control">
<span asp-validation-for="ArticleTitle" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ArticleContent" class="control-label"></label>
<textarea asp-for="ArticleContent" id="testCK" class="form-control"></textarea>
<span asp-validation-for="ArticleContent" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ImagePath" class="control-label"></label>
<br />
<img style="max-width: 100%; height: 200px;" src="#Model.ImagePath" class="rounded img-thumbnail" alt="Article Image" id="existingImage">
<input hidden asp-for="ImagePath" class="form-control" />
<div class="custom-file">
<input type="file" asp-for="ImagePath" onchange="readURL(this)" class="custom-file-input form-control" name="Image" id="customFile">
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
<span asp-validation-for="ImagePath" class="text-danger"></span>
<!-- Uploaded image area-->
<div class="image-area mt-4"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div>
</div>
<div class="form-group">
<input type="submit" value="Edit" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/ckeditor/ckeditor.js"></script>
<script>
var contentTextArea = document.getElementById("testCK")
CKEDITOR.replace(contentTextArea);
</script>
<script type="text/javascript">
$(".custom-file-input").on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
});
</script>
<script>
//Show Image
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imageResult')
.attr('src', e.target.result);
};
reader.readAsDataURL(input.files[0]);
}
var beforeImage = document.getElementById('existingImage');
beforeImage.style.display = 'none';
}
$(function () {
$('#customFile').on('change', function () {
readURL(input);
});
});
</script>
<script type="text/javascript">
//Show Image Name
document.querySelector('.custom-file-input').addEventListener('change', function (e) {
var name = document.getElementById("customFile").files[0].name;
var nextSibling = e.target.nextElementSibling
nextSibling.innerText = name
})
</script>
ArticleForm model
public class ArticleForm
{
public int ArticleId { get; set; }
[Required, Column(TypeName = "varchar(150)")]
[DisplayName("Article Title")]
public string ArticleTitle { get; set; }
[Required, Column(TypeName = "text")]
[DisplayName("Article Content")]
public string ArticleContent { get; set; }
public DateTime CreatedOn { get; set; }
[Column(TypeName = "text")]
[DisplayName("Image")]
public string ImagePath { get; set; }
public int[] AuthorIds { get; set; }
public int[] TagIds { get; set; }
}
Article Model
public class Article
{
public int ArticleId { get; set; }
public string ArticleTitle { get; set; }
public string ArticleContent { get; set; }
public DateTime CreatedOn { get; set; }
public string ImagePath { get; set; }
}
AuthorTagArticle Model
public class AuthorTagArticle
{
public Article Article { get; set; }
public List<User> Author { get; set; }
public List<Tag> Tag { get; set; }
}
GlobalVariables
public class GlobalVariables
{
public static HttpClient WebApiClient = new HttpClient();
static GlobalVariables()
{
//local testing
WebApiClient.BaseAddress = new Uri("https://localhost:44361/api/");
//lambda APIs
WebApiClient.DefaultRequestHeaders.Clear();
WebApiClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}
}
Try to edit your code as following: <form asp-controller="{Your controller}" asp-action="Edit" method="post">
Also you can read some info about Tag Helpers here

How to change uploaded image on Razor page asp.net core

I tried a file uploading method from StackOverflow and successfully uploaded the image with the IHostEnvironment setup. But I can't figure out the Editmodel. I want to delete the existing photo and add a new one in the edit form.
Here is Model:
[Key]
public int PostID { get; set; }
[Required]
[StringLength(160)]
public string Title { get; set; }
public string FeatureImage { get; set; }
Here is the Create.cshtml.cs:
public class CreateModel : PageModel
{
private readonly RazorApp.Data.ApplicationDbContext _context;
private readonly IHostEnvironment hostingEnvironment;
public CreateModel(RazorApp.Data.ApplicationDbContext context, IHostEnvironment environment)
{
this.hostingEnvironment = environment;
_context = context;
}
[BindProperty]
public Post Post { get; set; }
[BindProperty]
public IFormFile Image { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (this.Image != null)
{
var fileName = GetUniqueName(this.Image.FileName);
var uploads = Path.Combine(hostingEnvironment.ContentRootPath, "wwwroot/uploads");
var filePath = Path.Combine(uploads, fileName);
this.Image.CopyTo(new FileStream(filePath, FileMode.Create));
this.Post.FeatureImage = fileName; // Set the file name
}
var emptyPost = new Post();
if (await TryUpdateModelAsync<Post>(
emptyPost,
"post",
p => p.Title, p => p.FeatureImage))
{
_context.Post.Add(Post);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
return Page();
}
private string GetUniqueName(string fileName)
{
fileName = Path.GetFileName(fileName);
return Path.GetFileNameWithoutExtension(fileName)
+ "_" + Guid.NewGuid().ToString().Substring(0, 4)
+ Path.GetExtension(fileName);
}
}
As I said, uploading the image working fine. But I can't figure out for the edit.cshtml.cs. How can I delete the existing photo and add the new image?
Here is a working sample , you could refer to :
Edit.cshtml
<div class="col-md-4">
<form method="post" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Post.PostID" />
<div class="form-group">
<label asp-for="Post.Title" class="control-label"></label>
<input asp-for="Post.Title" class="form-control" />
<span asp-validation-for="Post.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Post.FeatureImage" class="control-label"></label>
<input asp-for="Post.FeatureImage" class="form-control" />
<span asp-validation-for="Post.FeatureImage" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">New Image</label>
<input asp-for="Image" class="form-control" />
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
Edit.cshtml.cs
public class EditModel : PageModel
{
private readonly ChangeUploadedImage.Data.MyDbContext _context;
private readonly IHostingEnvironment hostingEnvironment;
public EditModel(MyDbContext context, IHostingEnvironment environment)
{
_context = context;
hostingEnvironment = environment;
}
[BindProperty]
public Post Post { get; set; }
[BindProperty]
public IFormFile Image { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
if (this.Image != null)
{
var path = Path.Combine(hostingEnvironment.ContentRootPath, "wwwroot/uploads", Post.FeatureImage);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
var fileName = GetUniqueName(this.Image.FileName);
var uploads = Path.Combine(hostingEnvironment.ContentRootPath, "wwwroot/uploads");
var filePath = Path.Combine(uploads, fileName);
this.Image.CopyTo(new FileStream(filePath, FileMode.Create));
this.Post.FeatureImage = fileName;
}
_context.Attach(Post).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PostExists(Post.PostID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private string GetUniqueName(string fileName)
{
fileName = Path.GetFileName(fileName);
return Path.GetFileNameWithoutExtension(fileName)
+ "_" + Guid.NewGuid().ToString().Substring(0, 4)
+ Path.GetExtension(fileName);
}
}

Categories

Resources