了解しました。
前回のコードをベースに、さらに実務向けの改善を加えた新しいバージョンを提示します。
今回の変更点は以下の通りです。
- トランザクション処理を追加(更新の信頼性向上)
- ModelState を使ったサーバー側バリデーション
- ログ出力例を追加(例:
ILogger) - JavaScript 側で ローディング表示 を追加
- SweetAlert2 の confirm/cancel 両方の分岐処理 を明確化
1. Controller 側(更新アクション)
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using YourAppNamespace.Data;
using YourAppNamespace.Models;
public class PaymentsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly ILogger<PaymentsController> _logger;
public PaymentsController(ApplicationDbContext context, ILogger<PaymentsController> logger)
{
_context = context;
_logger = logger;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UpdatePayment(
[FromBody] PaymentUpdateDto dto,
CancellationToken cancellationToken)
{
if (!ModelState.IsValid || dto == null || dto.PaymentId <= 0)
{
return BadRequest(new { message = "入力データが不正です。" });
}
if (dto.Amount < 0)
{
return BadRequest(new { message = "金額は0以上で入力してください。" });
}
await using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
try
{
var payment = await _context.Payments
.FirstOrDefaultAsync(p => p.PaymentId == dto.PaymentId, cancellationToken);
if (payment == null)
{
return NotFound(new { message = "指定された支払いデータが見つかりません。" });
}
payment.IncomeCategoryId = dto.IncomeCategoryId;
payment.Amount = dto.Amount;
payment.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
_logger.LogInformation("Payment {PaymentId} updated successfully.", dto.PaymentId);
return Ok(new { message = "更新が完了しました。" });
}
catch (Exception ex)
{
await transaction.RollbackAsync(cancellationToken);
_logger.LogError(ex, "Payment update failed for ID {PaymentId}", dto.PaymentId);
return StatusCode(500, new { message = "更新処理中にエラーが発生しました。", error = ex.Message });
}
}
}
public class PaymentUpdateDto
{
public int PaymentId { get; set; }
public int IncomeCategoryId { get; set; }
public decimal Amount { get; set; }
}
2. View 側 JavaScript(SweetAlert2 + Ajax + ローディング表示)
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
}).then((result) => {
if (result.isConfirmed && paymentId && paymentId > 0) {
const data = {
paymentId: paymentId,
incomeCategoryId: result.value.incomeCategoryId,
amount: result.value.amount
};
Swal.fire({
title: '更新中...',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
$.ajax({
url: '/Payments/UpdatePayment',
type: 'POST',
contentType: 'application/json',
headers: {
'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
},
data: JSON.stringify(data),
success: function (response) {
Swal.fire({
icon: 'success',
title: '更新成功',
text: response.message,
confirmButtonText: 'OK'
}).then(() => {
location.reload();
});
},
error: function (xhr) {
let msg = xhr.responseJSON?.message || '不明なエラーが発生しました。';
Swal.fire({
icon: 'error',
title: '更新失敗',
text: msg,
confirmButtonText: '閉じる'
});
}
});
} else if (result.isDismissed) {
Swal.fire({
icon: 'info',
title: 'キャンセルしました',
timer: 1500,
showConfirmButton: false
});
}
});
</script>
3. 改良ポイント
- トランザクションで更新の信頼性を確保。
- ILogger で更新成功・失敗をログ出力。
- SweetAlert2 で ローディング表示 を追加し、処理中のユーザー体験を改善。
- キャンセル時の UI 表示を追加。
- エラー時の詳細メッセージを Ajax 側で取得して表示。
この形にすれば、安全性・可読性・ユーザー体験 のすべてを強化できます。
もし希望があれば、このコードを Index.cshtml に完全統合した動作版 として提供できます。
そうすれば、即動作確認が可能です。
この統合版を作成しますか?
Powered by Froala Editor