Sıra geldi uygulama soru ve cevaplarını hazırlamaya. Soru ve cevaplar için en yaygın kullanılan editör olan CKEditor kullanılacaktır. CKEditor, zengin metin düzenleme özellikleri sunarak, metinler üzerinde kolayca biçimlendirme yapmanızı sağlar. Bu tür bir işlevi ASP.NET Core projesi içerisinde nasıl yapabileceğinizi adım adım anlatacağım.
Öncelikle CKEditor'ü sayfanıza eklemeniz gerekmektedir. CKEditor'u CDN üzerinden ekleyebilirsiniz.
_Sablon.cshtml dosyasına CKEditor'un JavaScript dosyasını dahil edelim.
<script src="https://cdn.ckeditor.com/ckeditor5/38.0.0/classic/ckeditor.js"></script>
Controller'ınızda soru ve cevabı alacak bir Create metodu oluşturun. Bu metodda CKEditor'dan gelen veriyi alıp veritabanına kaydedebilirsiniz.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using OfficeOpenXml;
using SchoolManagement.Data;
using SchoolManagement.Models;
namespace SchoolManagement.Controllers
{
public class UygulamaController : Controller
{
private readonly ApplicationDbContext _context;
public UygulamaController(ApplicationDbContext context)
{
_context = context;
// EPPlus Lisansını ayarlıyoruz
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // Ücretsiz kullanım için
}
[HttpGet]
public IActionResult Index()
{
// Uygulamaları ve ilişkili dersleri çekiyoruz
var uygulamalar = _context.Uygulamalar
.Include(u => u.Ders)
.ToList();
return View("~/Views/Admin/Uygulama/Index.cshtml", uygulamalar);
}
[HttpGet]
public IActionResult Create()
{
// Derslerin listesini alıyoruz
var dersler = _context.Dersler.ToList();
ViewBag.Dersler = dersler; // Dersleri ViewBag ile view'a gönderiyoruz.
return View("~/Views/Admin/Uygulama/Create.cshtml");
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Uygulama uygulama)
{
if (!ModelState.IsValid)
{
// Hataları logla
var errors = ModelState.Values.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage)
.ToList();
foreach (var error in errors)
{
Console.WriteLine("ModelState Hatası: " + error);
}
// Formu tekrar yükle, Ders listesini tekrar gönder
var dersler = _context.Dersler.ToList();
ViewBag.Dersler = dersler; // Dersleri ViewBag ile view'a gönderiyoruz.
return View("~/Views/Admin/Uygulama/Create.cshtml", uygulama);
}
_context.Uygulamalar.Add(uygulama);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
[HttpGet]
public IActionResult Delete(int id)
{
// Silinecek uygulamayı alıyoruz
var uygulama = _context.Uygulamalar
.Include(u => u.Ders) // Eğer ilişkili ders bilgisi de gerekiyorsa
.FirstOrDefault(u => u.Id == id);
if (uygulama == null)
{
// Eğer böyle bir uygulama yoksa, hata mesajı döndürüyoruz.
return NotFound();
}
return View("~/Views/Admin/Uygulama/Delete.cshtml", uygulama);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public IActionResult DeleteConfirmed(int id)
{
var uygulama = _context.Uygulamalar.Find(id);
if (uygulama == null)
{
return NotFound();
}
// Silme işlemi yapılıyor
_context.Uygulamalar.Remove(uygulama);
_context.SaveChanges();
// Silme işlemi tamamlandıktan sonra Index sayfasına yönlendiriyoruz
return RedirectToAction(nameof(Index));
}
// Düzenle sayfasına veri gönderme (GET metodu)
[HttpGet]
public IActionResult Edit(int id)
{
// Veritabanından düzenlenecek uygulamayı alıyoruz
var uygulama = _context.Uygulamalar
.Include(u => u.Ders) // Ders bilgisini de dahil et
.FirstOrDefault(u => u.Id == id);
// Uygulama bulunamadıysa, 404 döndür
if (uygulama == null)
{
return NotFound();
}
// Düzenleme sayfasına veri gönder
var dersler = _context.Dersler.ToList(); // Dersleri al
ViewBag.Dersler = dersler;
return View("~/Views/Admin/Uygulama/Edit.cshtml", uygulama);
}
// Düzenleme işlemi (POST metodu)
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(int id, Uygulama uygulama)
{
if (id != uygulama.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
// Uygulama kaydını güncelliyoruz
_context.Update(uygulama);
_context.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
// Eğer bir hata oluşursa, kullanıcıya hata mesajı göster
if (!_context.Uygulamalar.Any(u => u.Id == id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index)); // Başarılı ise Index sayfasına yönlendir
}
// Hatalı model durumunda, tekrar ders listesi ile formu gönder
var dersler = _context.Dersler.ToList();
ViewBag.Dersler = dersler;
return View(uygulama);
}
[HttpGet]
public IActionResult Upload()
{
return View("~/Views/Admin/Uygulama/Upload.cshtml");
}
[HttpPost]
public async Task<IActionResult> Aktar(IFormFile file)
{
if (file != null && file.Length > 0)
{
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
// EPPlus ile Excel dosyasını okuyalım
using (var package = new ExcelPackage(stream))
{
var worksheet = package.Workbook.Worksheets[0]; // İlk sayfayı alıyoruz
int rowCount = worksheet.Dimension.Rows;
for (int row = 1; row <= rowCount; row++) // Başlık satırını atlıyoruz (row = 2)
{
var uygulama = new Uygulama
{
UygulamaAdi = worksheet.Cells[row, 1].Text, // 1. sütun -> Uygulama Adı
UygulamaSorusu = worksheet.Cells[row, 2].Text, // 2. sütun -> Soru
UygulamaCevabi = worksheet.Cells[row, 3].Text, // 3. sütun -> Cevap
DersId = Int32.Parse(worksheet.Cells[row, 4].Text) // 3. sütun -> Cevap
};
_context.Uygulamalar.Add(uygulama); // Veritabanına ekliyoruz
}
await _context.SaveChangesAsync(); // Veritabanına kaydediyoruz
}
}
return RedirectToAction("~/Views/Admin/Uygulama/Upload.cshtml"); // Başka bir aksiyona yönlendirebilirsiniz
}
return View("~/Views/Admin/Uygulama/Upload.cshtml");
}
}
}
Şimdi Index sayfasını hazırlayalım.
@model IEnumerable<SchoolManagement.Models.Uygulama>
@{
ViewData["Title"] = "Uygulamalar";
}
<h1>Uygulamalar</h1>
<p>
<a asp-action="Create" class="btn btn-primary">Yeni Uygulama Ekle</a>
</p>
<p>
<a asp-action="Upload" class="btn btn-primary">Excel'den Kayıt Aktar</a>
</p>
@if (Model == null || !Model.Any())
{
<div class="alert alert-info">
Henüz hiç uygulama kaydı bulunmamaktadır. Yeni uygulama eklemek için "Yeni Uygulama Ekle" butonunu kullanabilirsiniz.
</div>
}
else
{
<table class="table table-striped">
<thead>
<tr>
<th>Ders Adı</th>
<th>Uygulama Adı</th>
<th>Uygulama Sorusu</th>
<th>İşlemler</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.Ders.DersAdi</td>
<td>@item.UygulamaAdi</td>
<td>
@if (item.UygulamaSorusu.Length > 50)
{
@Html.Raw(RemoveHtmlTags(item.UygulamaSorusu.Substring(0, 50)) + "...")
}
else
{
@Html.Raw(RemoveHtmlTags(item.UygulamaSorusu))
}
</td>
<td>
<div class="btn-group">
<a asp-action="Edit" asp-route-id="@item.Id" class="btn btn-sm btn-warning">Düzenle</a> |
<a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-sm btn-danger">Sil</a>
</div>
</td>
</tr>
}
</tbody>
</table>
}
@functions {
public string RemoveHtmlTags(string input)
{
return System.Text.RegularExpressions.Regex.Replace(input, "<.*?>", string.Empty);
}
}
Create sayfasını hazırlayalım.
@model SchoolManagement.Models.Uygulama
@{
ViewData["Title"] = "Create Uygulama";
}
<h1>Create Uygulama</h1>
<form asp-controller="Uygulama" asp-action="Create" method="post">
@Html.AntiForgeryToken()
<div class="form-group mb-3">
<label for="UygulamaAdi">Uygulama Adı</label>
<input type="text" class="form-control" id="UygulamaAdi" name="UygulamaAdi" required />
</div>
<div class="form-group mb-3">
<label for="UygulamaSorusu">Uygulama Sorusu</label>
<textarea id="UygulamaSorusu" name="UygulamaSorusu" class="form-control"></textarea>
</div>
<div class="form-group mb-3">
<label for="UygulamaCevabi">Uygulama Cevabı</label>
<textarea id="UygulamaCevabi" name="UygulamaCevabi" class="form-control"></textarea>
</div>
<div class="form-group mb-3">
<label for="DersId">Ders</label>
<select id="DersId" name="DersId" class="form-control" required>
<option value="">-- Ders Seçiniz --</option>
@foreach (var ders in ViewBag.Dersler as List<SchoolManagement.Models.Ders>)
{
<option value="@ders.Id">@ders.DersAdi</option>
}
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Create</button>
<a asp-controller="Uygulama" asp-action="Index" class="btn btn-secondary">İptal</a>
</div>
</form>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", function () {
let soruEditor, cevapEditor;
ClassicEditor
.create(document.querySelector('#UygulamaSorusu'))
.then(editor => {
soruEditor = editor;
})
.catch(error => console.error("CKEditor yüklenirken hata oluştu:", error));
ClassicEditor
.create(document.querySelector('#UygulamaCevabi'))
.then(editor => {
cevapEditor = editor;
})
.catch(error => console.error("CKEditor yüklenirken hata oluştu:", error));
document.querySelector('form').addEventListener('submit', function (event) {
// CKEditor içeriğini textarea'ya aktarıyoruz
document.querySelector('#UygulamaSorusu').value = soruEditor.getData();
document.querySelector('#UygulamaCevabi').value = cevapEditor.getData();
// Eğer CKEditor alanları boşsa formu göndermiyoruz
if (!document.querySelector('#UygulamaSorusu').value.trim()) {
alert("Lütfen 'Uygulama Sorusu' alanını doldurunuz.");
event.preventDefault();
}
if (!document.querySelector('#UygulamaCevabi').value.trim()) {
alert("Lütfen 'Uygulama Cevabı' alanını doldurunuz.");
event.preventDefault();
}
});
});
</script>
}
Edit sayfasını hazırlayalım.
@model SchoolManagement.Models.Uygulama
@{
ViewData["Title"] = "Uygulama Düzenle";
}
<h1>@ViewData["Title"]</h1>
<form asp-action="Edit" method="post">
@Html.AntiForgeryToken()
<div class="form-group">
<label for="UygulamaAdi">Uygulama Adı</label>
<input type="text" class="form-control" id="UygulamaAdi" name="UygulamaAdi" value="@Model.UygulamaAdi" required />
</div>
<div class="form-group">
<label for="UygulamaSorusu">Uygulama Sorusu</label>
<textarea class="form-control" id="UygulamaSorusu" name="UygulamaSorusu" required>@Model.UygulamaSorusu</textarea>
</div>
<div class="form-group">
<label for="UygulamaCevabi">Uygulama Cevabı</label>
<textarea class="form-control" id="UygulamaCevabi" name="UygulamaCevabi" required>@Model.UygulamaCevabi</textarea>
</div>
<div class="form-group">
<label for="DersId">Ders</label>
<select class="form-control" id="DersId" name="DersId" required>
<option value="">Ders Seçiniz</option>
@foreach (var ders in ViewBag.Dersler as List<SchoolManagement.Models.Ders>)
{
@if (ders.Id == Model.DersId) // Koşulu burada kontrol ediyorsunuz
{
<option value="@ders.Id" selected>@ders.DersAdi</option>
}
else
{
<option value="@ders.Id">@ders.DersAdi</option>
}
}
</select>
</div>
<button type="submit" class="btn btn-primary">Kaydet</button>
<a asp-action="Index" class="btn btn-secondary">İptal</a>
</form>
<script>
// CKEditor ile 'UygulamaSorusu' alanını başlatıyoruz.
ClassicEditor
.create(document.querySelector('#UygulamaSorusu'))
.catch(error => {
console.error(error);
});
// CKEditor ile 'UygulamaCevabi' alanını başlatıyoruz.
ClassicEditor
.create(document.querySelector('#UygulamaCevabi'))
.catch(error => {
console.error(error);
});
</script>
Delete sayfasını hazırlayalım.
@model SchoolManagement.Models.Uygulama
@{
ViewData["Title"] = "Uygulama Sil";
}
<h1>Uygulama Sil</h1>
<p>Bu uygulamayı silmek istediğinizden emin misiniz?</p>
<div>
<strong>Uygulama Adı:</strong> @Model.UygulamaAdi
</div>
<div>
<strong>Uygulama Sorusu:</strong> @Model.UygulamaSorusu
</div>
<div>
<strong>Ders Adı:</strong> @Model.Ders.DersAdi
</div>
<form asp-action="Delete" method="post">
@Html.AntiForgeryToken()
<input type="hidden" name="id" value="@Model.Id" />
<div>
<button type="submit" class="btn btn-danger">Sil</button>
<a asp-action="Index" class="btn btn-secondary">İptal</a>
</div>
</form>
Excel dosyasını tabloya aktaran Upload sayfasını hazırlayalım.
@{
ViewData["Title"] = "Excel Yükle";
}
<h1>@ViewData["Title"]</h1>
<form asp-action="Aktar" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="file">Excel Dosyası Yükleyin</label>
<input type="file" name="file" class="form-control" required />
</div>
<button type="submit" class="btn btn-primary">Yükle</button>
</form>