ฉันได้ดู CQRS / MediatR เมื่อเร็ว ๆ นี้ แต่ยิ่งฉันเจาะลึกยิ่งฉันชอบมากเท่าไร บางทีฉันอาจเข้าใจผิดบางอย่าง / ทุกอย่าง
ดังนั้นมันจึงยอดเยี่ยมโดยอ้างว่าลดคอนโทรลเลอร์ของคุณลงไป
public async Task<ActionResult> Edit(Edit.Query query)
{
var model = await _mediator.SendAsync(query);
return View(model);
}
ซึ่งเข้ากันได้อย่างสมบูรณ์แบบกับชุดควบคุมแบบบาง อย่างไรก็ตามจะมีรายละเอียดที่สำคัญออกไปบ้าง
ให้ดูที่การLogin
กระทำเริ่มต้นจากโครงการ MVC ใหม่
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation(1, "User logged in.");
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning(2, "User account locked out.");
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
การแปลงที่นำเสนอเราด้วยปัญหามากมายในโลกแห่งความเป็นจริง จำไว้ว่าเป้าหมายคือลดมันลงไป
public async Task<IActionResult> Login(Login.Command command, string returnUrl = null)
{
var model = await _mediator.SendAsync(command);
return View(model);
}
ทางออกหนึ่งที่เป็นไปได้ในการทำเช่นนี้คือการส่งคืนCommandResult<T>
แทนmodel
แล้วจัดการกับCommandResult
ตัวกรองการดำเนินการโพสต์ ตามที่กล่าวไว้ที่นี่
หนึ่งในการนำไปปฏิบัติCommandResult
อาจเป็นเช่นนี้
public interface ICommandResult
{
bool IsSuccess { get; }
bool IsFailure { get; }
object Result { get; set; }
}
อย่างไรก็ตามนั่นไม่ได้แก้ปัญหาของเราในการLogin
ดำเนินการเพราะมีความล้มเหลวหลายสถานะ เราสามารถเพิ่มสถานะความล้มเหลวพิเศษเหล่านี้ได้ICommandResult
แต่นั่นเป็นการเริ่มต้นที่ยอดเยี่ยมสำหรับคลาส / อินเทอร์เฟซที่ป่องมาก อาจมีคนบอกว่ามันไม่สอดคล้องกับ Single Responsibility (SRP)
returnUrl
ปัญหาอีกประการหนึ่งคือ เรามีreturn RedirectToLocal(returnUrl);
รหัสชิ้นนี้ ยังไงก็เถอะเราจำเป็นต้องจัดการข้อโต้แย้งตามเงื่อนไขขึ้นอยู่กับสถานะความสำเร็จของคำสั่ง ในขณะที่ฉันคิดว่าสามารถทำได้ (ฉันไม่แน่ใจว่า ModelBinder สามารถแมป FromBody และ FromQuery ( returnUrl
คือ FromQuery) กับรูปแบบเดียว) มีเพียงคนเดียวที่สงสัยว่าสถานการณ์เลวร้ายแบบไหนที่จะเกิดขึ้นได้
การตรวจสอบรูปแบบมีความซับซ้อนมากขึ้นพร้อมกับส่งคืนข้อความแสดงข้อผิดพลาด ใช้สิ่งนี้เป็นตัวอย่าง
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
เราแนบข้อความแสดงข้อผิดพลาดพร้อมกับรุ่น สิ่งนี้ไม่สามารถทำได้โดยใช้Exception
กลยุทธ์ (ตามที่แนะนำไว้ที่นี่ ) เพราะเราต้องการโมเดล บางทีคุณสามารถรับแบบจำลองจากRequest
แต่มันจะเป็นกระบวนการที่เกี่ยวข้องมาก
ดังนั้นในทั้งหมดฉันมีเวลายากที่จะแปลงการกระทำ "ง่าย" นี้
ฉันกำลังมองหาปัจจัยการผลิต ฉันผิดที่นี่ทั้งหมดหรือไม่