> For the complete documentation index, see [llms.txt](https://sahin.gitbook.io/asp-net-core-el-kitab/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sahin.gitbook.io/asp-net-core-el-kitab/yeni-oezellikler-ekleme/maddeleri-onay-kutusu-ile-tamamlama.md).

# Maddeleri Onay Kutusu ile Tamamlama

Yapılacaklar listesine ekleme işini yaptınız çokta güzel oldu. Fakat bir de bu işin tamamlanması var. `Views/Todo/Index.cshtml` sayfasına göre her yapılacak için onay kutusunu da gösterilecek.

```markup
<input type="checkbox" name="@item.Id" value="true" class="done-checkbox">
```

Her maddenin bir benzersiz ID( guid )'si olduğundan bunu bullanabiliriz. Bunu name alanında belirterek kontrolöre bunu paslayarak bu maddeyi güncelleyebiliriz.

Akışın tamamı aşağıdaki gibi olacak

* Kullanıcı onay kutusunu işaretler ve Javascript fonksiyonu tetiklenir.
* Javascript kontrolöre talep gönderir.
* Kontrolörde bulunan aksiyon servis katmanına çağrıda bulunarak bu maddenin güncellenmesini sağlar.
* Güncelleme sonunda cevap Javascript fonksiyonuna geri gönderilir.
* HTML kodu güncellenir.

## Javascript Kodu Ekleme

Önce `site.js`'yi açık ve `$(document).ready` bloğunun içerisini aşağıdaki gibi düzenleyin.

**wwwroot/js/site.js**

```javascript
$(document).ready(function() {

    // ...

    // .done-checkbox sınıfına ait tüm onay kutuları aşağıdaki kodu çalıştırır.
    $('.done-checkbox').on('click', function(e) {
        markCompleted(e.target);
    });

});
```

Sonrasında sayfanın sonuna aşağıdaki kodu ekleyin:

```javascript
function markCompleted(checkbox) {
    checkbox.disabled = true;

    $.post('/Todo/MarkDone', { id: checkbox.name }, function() {
        var row = checkbox.parentElement.parentElement;
        $(row).addClass('done');
    });
}
```

Bu kod daha önceki yapılacak oluşturma fonksiyonu ile aynı yapıya sahip. Fakat bu defa HTTP POST ile `http://localhost:5000/Todo/MarkDone` adresine talep gönderip bunun içerisinde id olarak veri tabanından gelen ve onay kutusunun name kısmında belirttiğimiz `id`yi paslıyoruz.

Herhangi bir onay kutusunu işaretleyip tarayıcınızın Network Araçlarına bakacak olursanız talebi aşağıdaki gibi görebilirsiniz.

```
POST http://localhost:5000/Todo/MarkDone
Content-Type: application/x-www-form-urlencoded

id=<some guid>
```

`$.post` başarılı bir şekilde döndüğünde onay kutusunun bulunduğu satır'a `done` sınıfı eklenir. Bu sınıfa has stil değişikliği uygulanmış olur.

## Kontrolöre aksiyon ekleme

Sizin de tahmin edeceğiniz gibi, `TodoController` içerisine `MarkDone` aksiyonunu eklemeliyiz.

```csharp
public async Task<IActionResult> MarkDone(Guid id)
{
    if (id == Guid.Empty) return BadRequest();

    var successful = await _todoItemService.MarkDoneAsync(id);

    if (!successful) return BadRequest();

    return Ok();
}
```

Şimdi bu adımların üzerinden geçelim. Öncelikle `id` isminde bir `Guid` argümanı ekledik. Yani bu metodun Guid beklediğini bildirdik. Daha önce yazdığımız `AddItem` aksiyonunda `NewTodoItem` modeli kullanmıştık. Fakat bu defa beklentimiz sadece `id` olduğundan böyle bir sınıf yapmaya gerek yok. ASP.NET Core gelen değeri **guid** olarak ayrıştırmaya çalışacak.

Herhangi bir model oluşturmadığımızdan ve doğruluk tanımını `[Required]` yapmadığımızdan dolayı metodumuz içerisinde `ModelState` kelimesini kullanamıyoruz. Fakat bunun yerine `Guid.Empty` gibi bir kontrol ile boş olup olmadığını kontrol edebiliriz. Eğer boş ise BadRequest yani `400 Bad Request` dönderebiliriz.

```csharp
if (id == Guid.Empty) return BadRequest();
```

Sırada kontrolörün servisi veri tabanı güncellemesi için çağırması kaldı. Bu yeni bir metod olan `MarkDoneAsync` ile `ITodoItemService` üzerinde yapılmakta. Sonuç olarak eğer veri tabanı güncellemesi başarılı olursa true aksi halde false değeri döndürecek.

```csharp
var successful = await _todoItemService.MarkDoneAsync(id);
if (!successful) return BadRequest();
```

Sonuç olarak herşey düzgün bir şekilde çalıştıysa javascript'e `Ok()` yani `200 OK` değerini döndüreceğiz. Daha kompleks bir yapı ile JSON yapısında farklı veriler göndermekte mümkün fakat şimdilik buna ihtiyacımız yok.

## Servis Metodu Ekleme

İlk olarak `MarkDoneAsync`'i arayüze ekleyin:

`Services/ITodoItemService.cs`

```csharp
Task<bool> MarkDoneAsync(Guid id);
```

Sonra bunun uygulamasını `TodoItemService` üzerinde şu şekilde tamamlayın:

`Services/TodoItemService.cs`

```csharp
public async Task<bool> MarkDoneAsync(Guid id)
{
    var item = await _context.Items
        .Where(x => x.Id == id)
        .SingleOrDefaultAsync();

    if (item == null) return false;

    item.IsDone = true;

    var saveResult = await _context.SaveChangesAsync();
    return saveResult == 1; // One entity should have been updated
}
```

Bu metod Entity Framework Core'un `Where` komutunu kullanarak ID kolonuna göre arama yapmaktadır. `SingleOrDefaultAsync` metodu bulduğu satırı item'a atar eğer bulamaz ise bu durumda item `null` olur. Bunun kontrolünü yaptıktan sonra doğrudan false dönebiliriz. Eğer `item` boş değilse bunun sadece `IsDone` özelliğini ayarlayarak güncelleyebiliriz.

```csharp
item.IsDone = true;
```

`SaveChangesAsync` metodu uygulanana kadar yaptığımız değişiklikler sadece yerelde değişti.`SaveChangesAsync` çalıştıktan sonra kaç satırı güncellediyse onu dönderir. Bu durumda ya 1 tane gönderecek veya 0, ama 0 olursa bir yanlışlık olduğunu söyleyebileceğiz. Eğer 1 ise `true` aksi halde `false` döndereceğiz.

## Test

Uygulamayı çalıştırıp bazı onay kutularını işaretleyin. Sayfayı yenilediğinizde bu maddelerin yapılacaklar listesinden silindiğini göreceksiniz. Bunun nedeni `GetIncompleteItemsAsync` te bulunan `Where` filtresidir.

Şu anda, uygulama herkesçe görülebilen yapılacaklar listesi durumundadır. Eğer kişiye özel bir liste olsa daha kullanışlı olabilir. Bir sonraki bölümde, ASP.NET Core Identity kullanarak güvenlik ve kimlik denetleme özelliklerini entegre edeceğiz.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sahin.gitbook.io/asp-net-core-el-kitab/yeni-oezellikler-ekleme/maddeleri-onay-kutusu-ile-tamamlama.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
