public async Task <CourseDetailViewModel> EditCourseAsync(CourseEditInputModel inputModel) { CourseDetailViewModel viewModel = await courseService.EditCourseAsync(inputModel); memoryCache.Remove($"Course{inputModel.Id}"); return(viewModel); }
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)); }
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); }
public async Task <IActionResult> Edit(int id) { ViewData["Title"] = "Modifica corso"; CourseEditInputModel inputModel = await courseService.GetCourseForEditingAsync(id); return(View(inputModel)); }
[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); }
//----------------------------------------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 }
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)); }
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); }
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)); }
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); }
//--------------------------------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); }
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)); }
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}")); }
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)); }
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)); }
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); }