Exemplo n.º 1
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            CourseDetailViewModel viewModel = await courseService.EditCourseAsync(inputModel);

            memoryCache.Remove($"Course{inputModel.Id}");
            return(viewModel);
        }
Exemplo n.º 2
0
        public async Task <IActionResult> Edit(CourseEditInputModel inputModel)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    CourseDetailViewModel course = await courseService.EditCourseAsync(inputModel);

                    TempData["ConfirmationMessage"] = "I dati sono stati salvati con successo";
                    return(RedirectToAction(nameof(Detail), new { id = inputModel.Id }));
                }
                catch (CourseImageInvalidException)
                {
                    ModelState.AddModelError(nameof(CourseEditInputModel.Image), "L'immagine selezionata non è valida");
                }
                catch (CourseTitleUnavailableException)
                {
                    ModelState.AddModelError(nameof(CourseEditInputModel.Title), "Questo titolo già esiste");
                }
                catch (OptimisticConcurrencyException)
                {
                    ModelState.AddModelError("", "Spiacenti, il salvataggio non è andato a buon fine perché nel frattempo un altro utente ha aggiornato il corso. Ti preghiamo di aggiornare la pagina e ripetere le modifiche.");
                }
            }

            ViewData["Title"] = "Modifica corso";
            return(View(inputModel));
        }
Exemplo n.º 3
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            DataSet dataSet = await db.QueryAsync($"SELECT COUNT(*) FROM Courses WHERE Id={inputModel.Id}");

            if (Convert.ToInt32(dataSet.Tables[0].Rows[0][0]) == 0)
            {
                throw new CourseNotFoundException(inputModel.Id);
            }

            try
            {
                dataSet = await db.QueryAsync($"UPDATE Courses SET Title={inputModel.Title}, Description={inputModel.Description}, Email={inputModel.Email}, CurrentPrice_Currency={inputModel.CurrentPrice.Currency}, CurrentPrice_Amount={inputModel.CurrentPrice.Amount}, FullPrice_Currency={inputModel.FullPrice.Currency}, FullPrice_Amount={inputModel.FullPrice.Amount} WHERE Id={inputModel.Id}");
            }
            catch (SqliteException exc) when(exc.SqliteErrorCode == 19)
            {
                throw new CourseTitleUnavailableException(inputModel.Title, exc);
            }

            if (inputModel.Image != null)
            {
                try {
                    string imagePath = await imagePersister.SaveCourseImageAsync(inputModel.Id, inputModel.Image);

                    dataSet = await db.QueryAsync($"UPDATE Courses SET ImagePath={imagePath} WHERE Id={inputModel.Id}");
                }
                catch (Exception exc)
                {
                    throw new CourseImageInvalidException(inputModel.Id, exc);
                }
            }

            CourseDetailViewModel course = await GetCourseAsync(inputModel.Id);

            return(course);
        }
Exemplo n.º 4
0
        public async Task <IActionResult> Edit(int id)
        {
            ViewData["Title"] = "Modifica corso";
            CourseEditInputModel inputModel = await courseService.GetCourseForEditingAsync(id);

            return(View(inputModel));
        }
Exemplo n.º 5
0
        [HttpPost]                                                              //eseguiamo il metodo SOLO quando la richiesta é post (quando invio i dati)
        public async Task <IActionResult> Edit(CourseEditInputModel inputModel) //ricevo l'istanza riempita con tutti i dati
        {
            //verifica della validità dell'input (in base alle regole definite nel CourseEditInputModel)
            if (ModelState.IsValid)
            {
                //titolo valido: creiamo il corso e se tutto va bene, reindirizziamo l'utente alla pagina di elenco
                try
                {
                    //qui inoltre salviamo l'immagine sul disco
                    CourseDetailViewModel course = await courseService.EditCourseAsync(inputModel);  //passo il titolo (ricevuto nell'oggetto CourseCreateInputModel)

                    //imposto il messaggio di conferma
                    TempData["ConfirmationMessage"] = "I dati sono stati salvati con successo";
                    //redireziono alla pagina di dettaglio, creo un oggetto anonimo con proprietà id valorizzata con l'id del corso
                    return(RedirectToAction(nameof(Detail), new { id = inputModel.Id }));             //dopo aver eseguito l'azione, viene indirizzato alla pagina Index
                }
                catch (CourseImageInvalidException)
                {
                    ModelState.AddModelError(nameof(CourseEditInputModel.Image), "L'immagine selezionata non è valida");
                }
                catch (CourseTitleUnavailableException)
                {
                    //se si verifica l'exception: aggiungiamo l'errore al ModelState e la segnaliamo al docente
                    ModelState.AddModelError(nameof(CourseEditInputModel.Title), "Questo titolo é già esistente e in uso");
                }
                catch (OptimisticConcurrencyException)
                {
                    ModelState.AddModelError("", "Spiacenti, il salvataggio non è andato a buon fine perché nel frattempo un altro utente ha aggiornato il corso. Ti preghiamo di aggiornare la pagina e ripetere le modifiche.");
                }
            }

            ViewData["Title"] = "Modifica corso";
            return(View(inputModel)); //riceve l'oggetto popolato con tutti i dati
        }
        //-------------------------------------------Modifica corsi------------------------------------

        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            CourseDetailViewModel viewModel = await courseService.EditCourseAsync(inputModel);

            //invalidiamo la cache (vado a invalidare il dettalglio del corso)
            memoryCache.Remove($"Course{inputModel.Id}");
            return(viewModel);
        }
Exemplo n.º 7
0
        //----------------------------------------Modifica corso-------------------------------------------------------

        public async Task <IActionResult> Edit(int id)       //visualizza il form
        {
            ViewData["Title"] = "Modifica corso";
            CourseEditInputModel inputModel = await courseService.GetCourseForEditingAsync(id);

            //ritorno una view contenente l'istanza del form di modifica
            return(View(inputModel)); //riceve l'oggetto popolato con tutti i dati
        }
Exemplo n.º 8
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            //Recupero dell'entità Course
            //FindAsync: specializzato con le chiavi primarie, gli fornisco l'id
            Course course = await dbContext.Courses.FindAsync(inputModel.Id);

            if (course == null)
            {
                throw new CourseNotFoundException(inputModel.Id);
            }

            //...e lui ci recupererà il corso (collegato a quell'id) andando a richiamare i metodi presenti in Courses
            course.ChangeTitle(inputModel.Title);
            course.ChangePrices(inputModel.FullPrice, inputModel.CurrentPrice);
            course.ChangeDescription(inputModel.Description);
            course.ChangeEmail(inputModel.Email);

            //concorrenza ottimistica (prima di invocare il SaveAsync)
            //chiediamo il registro dell'entità (Entry(course) e la sua proprietà RowVersion a cui settiamo l'original value)
            //il valore fornito dall'input model é letto dal db
            dbContext.Entry(course).Property(course => course.RowVersion).OriginalValue = inputModel.RowVersion;

            if (inputModel.Image != null)
            {
                try{
                    string imagePath = await imagePersister.SaveCourseImageAsync(inputModel.Id, inputModel.Image);

                    //aggiorno solo l'image path con il nuovo percorso che é stato restituito
                    course.ChangeImagePath(imagePath);
                }
                catch (Exception ex) //immagine troppo grande!
                {
                    throw new CourseImageInvalidException(inputModel.Id, ex);
                }
            }

            //dbContext.Update(course); non necessario perché già l'entità course viene tracciata

            try
            {
                //SaveChangesAsync invia un comando update al database
                await dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                throw new OptimisticConcurrencyException();
            }
            catch (DbUpdateException ex) when((ex.InnerException as SqliteException)?.SqliteErrorCode == 19)
            {
                throw new CourseTitleUnavailableException(inputModel.Title, ex);
            }

            return(CourseDetailViewModel.FromEntity(course));
        }
Exemplo n.º 9
0
        public async Task <CourseEditInputModel> GetCourseForEditingAsync(int id)
        {
            IQueryable <CourseEditInputModel> queryLinq = dbContext.Courses
                                                          .AsNoTracking()
                                                          .Where(course => course.Id == id)
                                                          .Select(course => CourseEditInputModel.FromEntity(course)); //Usando metodi statici come FromEntity, la query potrebbe essere inefficiente. Mantenere il mapping nella lambda oppure usare un extension method personalizzato
            CourseEditInputModel viewModel = await queryLinq.FirstOrDefaultAsync();

            if (viewModel == null)
            {
                logger.LogWarning("Course {id} not found", id);
                throw new CourseNotFoundException(id);
            }
            return(viewModel);
        }
Exemplo n.º 10
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            Course course = await dbContext.Courses.FindAsync(inputModel.Id);

            if (course == null)
            {
                throw new CourseNotFoundException(inputModel.Id);
            }

            course.ChangeTitle(inputModel.Title);
            course.ChangePrices(inputModel.FullPrice, inputModel.CurrentPrice);
            course.ChangeDescription(inputModel.Description);
            course.ChangeEmail(inputModel.Email);

            dbContext.Entry(course).Property(course => course.RowVersion).OriginalValue = inputModel.RowVersion;

            if (inputModel.Image != null)
            {
                try
                {
                    string imagePath = await imagePersister.SaveCourseImageAsync(inputModel.Id, inputModel.Image);

                    course.ChangeImagePath(imagePath);
                }
                catch (Exception exc)
                {
                    throw new CourseImageInvalidException(inputModel.Id, exc);
                }
            }

            //dbContext.Update(course);

            try
            {
                await dbContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                throw new OptimisticConcurrencyException();
            }
            catch (DbUpdateException exc) when((exc.InnerException as SqliteException)?.SqliteErrorCode == 19)
            {
                throw new CourseTitleUnavailableException(inputModel.Title, exc);
            }

            return(CourseDetailViewModel.FromEntity(course));
        }
Exemplo n.º 11
0
        public async Task <CourseEditInputModel> GetCourseForEditingAsync(int id)
        {
            FormattableString query = $@"SELECT Id, Title, Description, ImagePath, Email, FullPrice_Amount, FullPrice_Currency, CurrentPrice_Amount, CurrentPrice_Currency, RowVersion FROM Courses WHERE Id={id} AND Status<>{nameof(CourseStatus.Deleted)}";

            DataSet dataSet = await db.QueryAsync(query);

            DataTable courseTable = dataSet.Tables[0];

            if (courseTable.Rows.Count != 1)
            {
                logger.LogWarning("Course {id} not found", id);
                throw new CourseNotFoundException(id);
            }
            DataRow courseRow = courseTable.Rows[0];
            CourseEditInputModel courseEditInputModel = CourseEditInputModel.FromDataRow(courseRow);

            return(courseEditInputModel);
        }
Exemplo n.º 12
0
        //--------------------------------Modifica corso-----------------------------------------

        public async Task <CourseEditInputModel> GetCourseForEditingAsync(int id)
        {
            //seleziona tutti i campi modificabili
            FormattableString query = $@"SELECT Id, Title, Description, ImagePath, Email, FullPrice_Amount, FullPrice_Currency, CurrentPrice_Amount, CurrentPrice_Currency, RowVersion FROM Courses WHERE Id={id}";

            DataSet dataSet = await db.ExecuteQueryAsync(query);

            var courseTable = dataSet.Tables[0];

            if (courseTable.Rows.Count != 1)                //se vengono trovate 0 righe: corso ... non trovato
            {
                logger.LogWarning("Course {id} not found", id);
                throw new CourseNotFoundException(id);      //richiama la classe dove é stata dichiarata l'eccezione
            }
            var courseRow = courseTable.Rows[0];
            //mapping sul CourseEditInputModel
            var courseEditInputModel = CourseEditInputModel.FromDataRow(courseRow);

            return(courseEditInputModel);
        }
Exemplo n.º 13
0
        public async Task <IActionResult> Edit(CourseEditInputModel inputModel)
        {
            if (ModelState.IsValid)
            {
                //Persisto i dati
                try
                {
                    CourseDetailViewModel course = await courseService.EditCourseAsync(inputModel);

                    TempData["ConfirmationMessage"] = "Aggiornamento eseguito correttamente";
                    return(RedirectToAction(nameof(Detail), new { id = inputModel.Id }));
                }
                catch (CourseTitleUnavailableException)
                {
                    ModelState.AddModelError(nameof(CourseDetailViewModel.Title), "Questo titolo esiste gi�");
                }
            }
            ViewData["Title"] = "Modifica corso";
            return(View(inputModel));
        }
Exemplo n.º 14
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            try
            {
                string imagePath = null;
                if (inputModel.Image != null)
                {
                    imagePath = await imagePersister.SaveCourseImageAsync(inputModel.Id, inputModel.Image);
                }
                int affectedRows = await db.CommandAsync($"UPDATE Courses SET ImagePath=COALESCE({imagePath}, ImagePath), Title={inputModel.Title}, Description={inputModel.Description}, Email={inputModel.Email}, CurrentPrice_Currency={inputModel.CurrentPrice.Currency.ToString()}, CurrentPrice_Amount={inputModel.CurrentPrice.Amount}, FullPrice_Currency={inputModel.FullPrice.Currency.ToString()}, FullPrice_Amount={inputModel.FullPrice.Amount} WHERE Id={inputModel.Id} AND Status<>{nameof(CourseStatus.Deleted)} AND RowVersion={inputModel.RowVersion}");

                if (affectedRows == 0)
                {
                    bool courseExists = await db.QueryScalarAsync <bool>($"SELECT COUNT(*) FROM Courses WHERE Id={inputModel.Id} AND Status<>{nameof(CourseStatus.Deleted)}");

                    if (courseExists)
                    {
                        throw new OptimisticConcurrencyException();
                    }
                    else
                    {
                        throw new CourseNotFoundException(inputModel.Id);
                    }
                }
            }
            catch (ConstraintViolationException exc)
            {
                throw new CourseTitleUnavailableException(inputModel.Title, exc);
            }
            catch (ImagePersistenceException exc)
            {
                throw new CourseImageInvalidException(inputModel.Id, exc);
            }

            CourseDetailViewModel course = await GetCourseAsync(inputModel.Id);

            return(course);
        }
        public async Task <IActionResult> Edit(CourseEditInputModel courseEditInputModel)
        {
            if (!DateTime.TryParseExact(courseEditInputModel.DateTime, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result))
            {
                throw new InvalidOperationException(InvalidDateTimeFormatErrorMessage);
            }

            if (await this.courseService.ExistsAsync(courseEditInputModel.Id) == false)
            {
                return(this.RedirectToAction("Error", "Home"));
            }

            if (!this.ModelState.IsValid)
            {
                return(this.View(courseEditInputModel));
            }

            var editCourseServiceModel = AutoMapperConfig.MapperInstance.Map <EditCourseServiceModel>(courseEditInputModel);

            await this.courseService.EditAsync(editCourseServiceModel);

            return(this.Redirect($"/Courses/Details/{editCourseServiceModel.Id}"));
        }
Exemplo n.º 16
0
        public async Task <IActionResult> Edit(CourseEditInputModel inputModel)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    CourseDetailViewModel course = await courseService.EditCourseAsync(inputModel);

                    TempData["ConfirmationMessage"] = "I dati sono stati salvati con successo";
                    return(RedirectToAction(nameof(Detail), new { id = inputModel.Id }));
                }
                catch (CourseImageInvalidException)
                {
                    ModelState.AddModelError(nameof(CourseEditInputModel.Image), "L'immagine selezionata non è valida");
                }
                catch (CourseTitleUnavailableException)
                {
                    ModelState.AddModelError(nameof(CourseEditInputModel.Title), "Questo titolo già esiste");
                }
            }

            ViewData["Title"] = "Modifica corso";
            return(View(inputModel));
        }
Exemplo n.º 17
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            Course course = await dbContext.Courses.FindAsync(inputModel.Id);

            if (course == null)
            {
                throw new CourseNotFoundException(inputModel.Id);
            }

            course.ChangeTitle(inputModel.Title);
            course.ChangePrices(inputModel.FullPrice, inputModel.CurrentPrice);
            course.ChangeDescription(inputModel.Description);
            course.ChangeEmail(inputModel.Email);
            try
            {
                await dbContext.SaveChangesAsync();
            }
            catch (DbUpdateException exc) when((exc.InnerException as SqliteException)?.SqliteErrorCode == 19)
            {
                throw new CourseTitleUnavailableException(inputModel.Title, exc);
            }

            return(CourseDetailViewModel.FromEntity(course));
        }
Exemplo n.º 18
0
        public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel)
        {
            //verifica quante righe esistono con quell'id
            //se ritorna 0: non c'é alcun corso corrispondente al criterio

            /*bool courseExists = await db.ExecuteQueryScalarAsync<bool>($"SELECT COUNT(*) FROM Courses WHERE Id={inputModel.Id}");
             * if (!courseExists)
             * {
             *  throw new CourseNotFoundException(inputModel.Id);   //e sollevo un eccezione impedendo lo svolgimento delle funzioni a seguire
             * }*/

            try
            {
                string imagePath = null;
                if (inputModel.Image != null)
                {
                    imagePath = await imagePersister.SaveCourseImageAsync(inputModel.Id, inputModel.Image);
                }
                //COALESCE: può accettare un qualsiasi numero di argomenti e restituisce il primo che trova NON NULL
                //se image path é null (nessuna img fornita), restituisce il valore stesso del campo imagePath (riassegnato su se stesso)

                int affectedRows = await db.CommandAsync($"UPDATE Courses SET ImagePath=COALESCE({imagePath}, ImagePath), Title={inputModel.Title}, Description={inputModel.Description}, Email={inputModel.Email}, CurrentPrice_Currency={inputModel.CurrentPrice.Currency.ToString()}, CurrentPrice_Amount={inputModel.CurrentPrice.Amount}, FullPrice_Currency={inputModel.FullPrice.Currency.ToString()}, FullPrice_Amount={inputModel.FullPrice.Amount} WHERE Id={inputModel.Id} AND RowVersion={inputModel.RowVersion}");

                if (affectedRows == 0)  //se il numero di righe interessate é 0
                {
                    //verifichiamo se il corso esiste
                    bool courseExists = await db.ExecuteQueryScalarAsync <bool>($"SELECT COUNT(*) FROM Courses WHERE Id={inputModel.Id}"); //count = 1: corso esistente, count = 0: corso non esiste

                    if (courseExists)                                                                                                      //se il corso esiste
                    {
                        //allora é fallito il controllo sulla rowVersion (concorrenza ottimistica)
                        throw new OptimisticConcurrencyException();
                    }
                    else //se il corso non dovesse esistere
                    {
                        throw new CourseNotFoundException(inputModel.Id);
                    }
                }
            }
            catch (ConstraintViolationException ex)
            {
                //eccezione personalizzata: creazione del corso fallita perché il titolo é già in utilizzo da un altro corso
                throw new CourseTitleUnavailableException(inputModel.Title, ex);
            }
            catch (ImagePersistenceException ex) //immagine troppo grande!
            {
                throw new CourseImageInvalidException(inputModel.Id, ex);
            }

            /*if (inputModel.Image != null)
             * {
             *  try{
             *      string imagePath = await imagePersister.SaveCourseImageAsync(inputModel.Id, inputModel.Image);
             *      //aggiorno solo l'image path con il nuovo percorso che é stato restituito
             *      dataSet = await db.ExecuteQueryAsync($"UPDATE Courses SET ImagePath={imagePath} WHERE Id={inputModel.Id}");
             *  }
             *  catch(Exception ex) //immagine troppo grande!
             *  {
             *      throw new CourseImageInvalidException(inputModel.Id, ex);
             *  }
             *
             * }*/

            CourseDetailViewModel course = await GetCourseAsync(inputModel.Id);

            return(course);
        }