家のステータスを更新するためのPOSTリクエストを作成したいとしましょう。理想的には、このデータはある種のサービスレイヤーにある必要があります。通常、これには次のものが含まれます。
- ユーザーを検証します-それらはまだアクティブですか、それとも管理者によって追い出されていますか?
- houseidを確認してください-houseid/レコードは有効ですか?
- ユーザーは家の詳細を見ることができますか?
- ステータスを「オープン」または「クローズ」に更新
現実の世界/複雑なドメイン-ほとんどのビューは非常に複雑です。おそらく、その地域の家の数、家に関するコメントの数、家の詳細など、家の未解決のタスクの数を破棄する必要があります。 ..。。
つまり、上記のコードはすべてサービスレイヤー内にある可能性がありますが、例外がスローされた場合、ユーザーは家のステータスを更新できません。ビューにデータを入力するには、最初に家の詳細を取得する必要があります。サービスレイヤー内にロードした他のすべてのものをコントローラー内にロードするか、このデータをロードするサービスレイヤーへの別のインコベーション...
同じコードを何度も書き直すことなく、検証とすべての種類を実行して、ドメインモデルが保護されていることを確認するにはどうすればよいですか...
このコードはactionメソッド内にあり、サービスレイヤー内に簡単に含めることができます...
//注:_repoは、linqからsqlへの単純な抽象化です...
[HttpGet]
public ActionResult TaskDetail(int houseid, int taskid)
{
var loggedonuser = _repo.GetCurrentUser();
var _house = _repo.Single<House>(x => x.HouseID == houseid && x.Handler == loggedonuser.CompanyID);
if (_house == null)
throw new NoAccessException();
var summary = _house.ToSummaryDTO();
var companies = _repo.All<Company>();
var users = _repo.All<User>();
var task = _repo.Single<HouseTask>
(x => x.HouseID == _house.HouseID && x.TaskID == taskid && (x.CompanyID == loggedonuser.CompanyID));
var dto = new TaskDTO
{
TaskID = task.TaskID,
Title = task.Title,
Description = task.Description,
DateCreated = task.DateCreated,
IsClosed = task.IsClosed,
CompanyID = companies.Where(y => task.CompanyID == y.CompanyID).SingleOrDefault().Identifier,
};
if (task.DueDate.HasValue)
dto.DueDate = task.DueDate.Value;
var comments = _repo.All<HouseTaskComment>()
.Where(x => x.TaskID == task.TaskID)
.OrderByDescending(x => x.Timestamp)
.Select(x => new TaskCommentDTO
{
Comment = x.Comment,
Timestamp = x.Timestamp,
CompanyID = companies.Where(y => x.CompanyID == y.CompanyID).SingleOrDefault().Identifier,
UserID = users.Where(y => x.UserID == y.UserID).SingleOrDefault().Login,
Type = EnumHelper.Convert<TaskCommentType>(x.Type)
});
dto.AllComments = comments;
return View(new TaskViewModel
{
Summary = summary,
TaskDetail = dto,
NewComment = new TaskCommentDTO()
});
}
要するに-要約の家の詳細を取得し、(複数の利用可能なタスクから)タスクの詳細を取得し、タスクのコメントも取得します。それは私見の単純な見方であり、それほど複雑なものではありません。
この時点で、ユーザーは次のことができます。コメントの追加、タスクの閉じる/開く-権限がある場合(簡単にするためにコードは省略)、タスクの期日を設定するか、タスクの期日をクリアすることもできます。
UpdateTaskStatus-ステータスを更新できない場合は、コメントと同様に上記のビューを返す必要があります。コメントできない場合は、詳細ビューを返す必要があります-コメントを閉じることができます。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult TaskDueDate(int houseid, int taskid)
{
var duedate = Request.Form["duedate"];
var duetime = Request.Form["duetime"];
try
{
if (ModelState.IsValid)
{
var newduedate = DateHelper.GoodDate(duedate, duetime);
_service.SetTaskDueDate(houseid, taskid, newduedate);
return RedirectToAction("TaskDetail");
}
}
catch (RulesException ex)
{
ex.CopyTo(ModelState);
}
var loggedonuser = _repo.GetCurrentUser();
var _house = _repo.Single<House>(x => x.InstructionID == houseid && x.HandlerID == loggedonuser.CompanyID);
if (_house == null)
throw new NoAccessException();
var summary = _house.ToSummaryDTO();
var companies = _repo.All<Company>();
var users = _repo.All<User>();
var task = _repo.Single<HouseTask>
(x => x.InstructionID == _house.HouseID && x.CompanyID == loggedonuser.CompanyID && x.TaskID == taskid);
var dto = new TaskDTO
{
TaskID = task.TaskID,
Title = task.Title,
Description = task.Description,
DateCreated = task.DateCreated,
IsClosed = task.IsClosed,
CompanyID = companies.Where(y => task.CompanyID == y.CompanyID).SingleOrDefault().Identifier
};
if (task.DueDate.HasValue)
dto.DueDate = task.DueDate.Value;
var comments = _repo.All<HouseTaskComment>()
.Where(x => x.TaskID == task.TaskID)
.OrderByDescending(x => x.Timestamp)
.Select(x => new TaskCommentDTO
{
Comment = x.Comment,
Timestamp = x.Timestamp,
CompanyID = companies.Where(y => x.CompanyID == y.CompanyID).SingleOrDefault().Identifier,
UserID = users.Where(y => x.UserID == y.UserID).SingleOrDefault().Login
});
dto.AllComments = comments;
return View("TaskDetail", new TaskViewModel
{
Summary = summary,
TaskDetail = dto,
NewComment = new TaskCommentDTO()
});
}
私は上記のコードがひどく構造化されていることを知っていますが、それを修正する方法についてのアドバイスをいただければ幸いです。
- アクション内にすべての読み取り専用コードを残します。各ビューが異なる可能性があるため、ここでサービスレイヤーが干渉することは望ましくありません。
- 更新/編集を「保護」し、これをサービスレイヤーまたはコアプロジェクト(個別のc#クラスライブラリ)またはドメインレイヤー内に保持したいのですが、そのコードハンドル検証をどのように記述しますか(これはサービス内で行います)呼び出し)、実際の保存を実行しますか?
CommandHandlerアプローチについて聞いたことがありますが、これは良いアプローチですか?理想的には、コントローラーアクションではなく、ドメイン内の単純なアプローチを使用して、検証と永続性を保持したいと思います。