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 MultipleChoiceTrainer.Data; using MultipleChoiceTrainer.Models; using MultipleChoiceTrainer.Models.DataModels; namespace MultipleChoiceTrainer.Controllers { public class QuestionsController : Controller { private readonly ApplicationDbContext _context; private readonly IWebHostEnvironment _webHostEnvironment; public QuestionsController(ApplicationDbContext context, IWebHostEnvironment hostEnvironment) { _context = context; _webHostEnvironment = hostEnvironment; } public IActionResult List(int sectionId) { return View(_context.Questions.Include(e => e.Choices).Where(e => e.SectionId == sectionId)); } // GET: Questions/Create public IActionResult Create(int sectionId) { ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == sectionId); return View(); } // POST: Questions/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 Create(QuestionViewModel question) { if (ModelState.IsValid) { question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList(); CopyUploadedFile(question); _context.Add(question as Question); await _context.SaveChangesAsync(); var section = _context.Sections.FirstOrDefault(s => s.Id == question.SectionId); return RedirectToAction(nameof(Index), "Home", new { categoryId = section.CategoryId }); } ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId); return View(question); } // GET: Questions/Edit/5 public async Task Edit(int? id) { if (id == null) { return NotFound(); } var question = _context.Questions.Include(e => e.Choices).FirstOrDefault(e => e.Id == id); if (question == null) { return NotFound(); } ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId); var vm = new QuestionViewModel() { Choices = question.Choices, Image = question.Image, Id = question.Id, SectionId = question.SectionId, Text = question.Text }; return View(vm); } // POST: Questions/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 Edit(int id, QuestionViewModel question) { if (id != question.Id) { return NotFound(); } if (ModelState.IsValid) { var deletedChoices = question.Choices.Where(e => (string.IsNullOrEmpty(e.Text) || string.IsNullOrWhiteSpace(e.Text)) && e.Id != 0).Select(e => e.Id).ToList(); question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList(); CopyUploadedFile(question); try { _context.Update(question as Question); await _context.SaveChangesAsync(); if(deletedChoices.Any()) { var q = _context.Questions.Include(e => e.Choices).First(e => e.Id == id); q.Choices.RemoveAll(e => deletedChoices.Contains(e.Id)); await _context.SaveChangesAsync(); } } catch (DbUpdateConcurrencyException) { if (!QuestionExists(question.Id)) { return NotFound(); } else { throw; } } return RedirectToAction(nameof(List), new { sectionId = question.SectionId }); } ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId); return View(question); } private bool QuestionExists(int id) { return _context.Questions.Any(e => e.Id == id); } private void CopyUploadedFile(QuestionViewModel model) { if (model.QuestionImage != null) { string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "uploads", "images", "questions"); Directory.CreateDirectory(uploadsFolder); model.Image = Guid.NewGuid().ToString() + Path.GetExtension(model.QuestionImage.FileName); string filePath = Path.Combine(uploadsFolder, model.Image); using (var fileStream = new FileStream(filePath, FileMode.Create)) { model.QuestionImage.CopyTo(fileStream); } } } } }