신청서에는 CQRS가 있습니다 : IAsyncCommand
은 IAsyncCommandHandler<IAsyncCommand>
입니다.MVC5 비동기 ActionResult. 그게 가능하니?
보통 명령은 다음과 같이 중재자를 통해 처리됩니다 잘 작동
var mediator = //get mediator injected into MVC controller via constructor
var asyncCommand = // construct AsyncCommand
// mediator runs ICommandValidator and that returns a list of errors if any
var errors = await mediator.ProcessCommand(asyncCommand);
합니다. 이제 나는 컨트롤러 액션에서 반복적 인 코드를 많이 수행한다는 것을 알게되었습니다 :
public async virtual Task<ActionResult> DoStuff(DoStuffAsyncCommand command)
{
if (!ModelState.IsValid)
{
return View(command);
}
var result = await mediator.ProcessCommandAsync(command);
if (!result.IsSuccess())
{
AddErrorsToModelState(result);
return View(command);
}
return RedirectToAction(MVC.HomePage.Index());
}
그리고이 패턴은 많은 컨트롤러에서 반복해서 반복됩니다. 그래서 단일 스레드 명령에 내가했던 단순화 :
public class ProcessCommandResult<T> : ActionResult where T : ICommand
{
private readonly T command;
private readonly ActionResult failure;
private readonly ActionResult success;
private readonly IMediator mediator;
public ProcessCommandResult(T command, ActionResult failure, ActionResult success)
{
this.command = command;
this.success = success;
this.failure = failure;
mediator = DependencyResolver.Current.GetService<IMediator>();
}
public override void ExecuteResult(ControllerContext context)
{
if (!context.Controller.ViewData.ModelState.IsValid)
{
failure.ExecuteResult(context);
return;
}
var handlingResult = mediator.ProcessCommand(command);
if (handlingResult.ConainsErrors())
{
AddErrorsToModelState(handlingResult);
failure.ExecuteResult(context);
}
success.ExecuteResult(context);
}
// plumbing code
}
그리고 일부 배관 공사 완료 후, 내 컨트롤러 액션은 다음과 같습니다
가 :public virtual ActionResult Create(DoStuffCommand command)
{
return ProcessCommand(command, View(command), RedirectToAction(MVC.HomePage.Index()));
}
이 내가 돈 동기화-명령에 대해 잘 작동 ' 패턴을 async-await
할 필요가 없습니다. async
작업을 시도하자마자 MVC에 AsyncActionResult
이 없기 때문에 컴파일되지 않으며 MVC 프레임 워크에서 비동기 작업을 void ExecuteResult(ControllerContext context)
에서 사용할 수 없습니다.
그럼, 내가 어떻게 질문의 맨 위에 인용 컨트롤러 작업의 일반적인 구현을 만들 수있는 아이디어?
'AsyncActionResult'라는 이름의 항목이 어디에 연관되는지 알 수 없습니다. 제네릭 메서드를 구현하는 경우 작업 또는 작업 만 반환하면됩니다. 비동기 작업은 항상 작업을 반환합니다. 'async void'는 비동기 이벤트 핸들러 (또는 메소드와 같은 핸들러)와 * nowhere * else에서만 사용되는 매우 특정한 구문입니다. 비동기적인'void' 메쏘드는'Task'를 리턴하는 함수입니다. 함수의 동등한 기능은'Task ' –
@PanagiotisKanavos를 반환하는 함수입니다. 예, 저는'async void'를 사용해서는 안된다는 것을 잘 알고 있습니다. 그리고 Mediator를 실행하기 전에'ModelState'가 유효한 상태인지 확인해야하기 때문에 Task를 반환 할 수 없습니다. MVC 파이프 라인을 통과하고 프레임 워크에서'ModelState'를 어떻게 든 꺼내야합니다. –
trailmax
액션 자체가 들어오는 요청과 예상되는 결과와 같은 다른 관심사가 섞여있는 것처럼 보입니다. 이 시점에서 ProcessCommandResult 클래스는 Controller처럼 보입니다. 유효성 검사, 바인딩 등을 무시하려면 MVC에 다른 메커니즘이 있습니다. 실제로 여기에있는 것은 CQRS를 위반합니다. ICommand를 구현하여 명령 자체처럼 응답 (ActionResult)을 사용하고 있습니다. –