Asp.net mvc asp.net mvc控制器发布最佳实践
我对“最佳实践”控制器使用问题有点困惑 我典型的代码外观Asp.net mvc asp.net mvc控制器发布最佳实践,asp.net-mvc,asp.net-mvc-3,controller,Asp.net Mvc,Asp.net Mvc 3,Controller,我对“最佳实践”控制器使用问题有点困惑 我典型的代码外观 public ActionResult Edit(int reportId,FormCollection formCollection) { try { var report = _dbContext.EmployeeReports.Find(reportId); if (TryUpdateModel(report))
public ActionResult Edit(int reportId,FormCollection formCollection)
{
try
{
var report = _dbContext.EmployeeReports.Find(reportId);
if (TryUpdateModel(report))
{
_employeeReportService.Update(report);
return RedirectToAction("List");
}
return View("Edit", report);
}
catch (Exception)
{
// some logging etc
return RedirectToAction("List");
}
好的,使用“TryUpdateModel”更好,还是只使用“UpdateModel”或简单调用模型更好。是有效的,在控制器中捕获异常是个好主意
谢谢以下是我更喜欢的另一种方式:
[HttpPost]
public ActionResult Edit(ReportViewModel reportViewModel)
{
if (!ModelState.IsValid)
{
// there were validation errors => redisplay the form
// so that the user can fix them
return View(reportViewModel);
}
// At this stage the view model is valid => we can
// map it back to a domain model and pass to the repository
// for processing
// Fetch the domain model that we want to update
var report = _repository.Get(reportViewModel.Id);
// map the domain model properties from the view model properties
// in this example I use AutoMapper
Mapper.Map<ReportViewModel, Report>(reportViewModel, report);
// perform update
_repository.Update(report);
// the update wen fine => we can redirect back to the list action
return RedirectToAction("List");
}
[HttpPost]
公共操作结果编辑(ReportViewModel ReportViewModel)
{
如果(!ModelState.IsValid)
{
//存在验证错误=>重新显示表单
//以便用户可以修复它们
返回视图(reportViewModel);
}
//在这个阶段,视图模型是有效的=>我们可以
//将其映射回域模型并传递到存储库
//处理
//获取要更新的域模型
var report=_repository.Get(reportViewModel.Id);
//从视图模型属性映射域模型属性
//在这个例子中,我使用AutoMapper
Map(reportViewModel,report);
//执行更新
_更新(报告);
//update wen fine=>我们可以重定向回list操作
返回重定向到操作(“列表”);
}
因此,正如您所看到的,没有
FormCollection
、没有TryUpdateModel
、没有UpdateModel
、没有try/catch
这取决于您是否期望并计划处理异常
我通常的做法是:
public ActionResult foobar(FormCollection formCollection)
{
//Keep this out of the try catch scope in case you need to pass it
// to the next method.
Model model = new Model();
try
{
if(!TryUpdateModel(model)
{
//Update Failed so fix it and redirect
return redirectToAction("fixit");
}
if(!ModelState.IsValid())
{
//Update worked but model state was invalid, return to page to correct
//model validation errors
return View("foobar", model);
}
//Update Succeeded so do other stuff
}
catch(Exception ex)
{
//Deal with Exception
return redirectToAction("ErrorView", "ErrorController");
}
return redirectToAction("NextStep");
}
我尝试在代码中使用所有这些模型,以在问题出现之前捕获问题。根据我的意见,您应该始终使用视图模型,而不是formcollection,以避免发布不足和发布过度的问题。因此,根据我的意见,最佳实践是使用视图模型来呈现视图,以及一种post/get模型,该模型精确绑定到您希望用户在某个操作中发布/获取的内容
这可能需要一些额外的工作,一些视图模型看起来与您在控制器操作中用于绑定的模型非常相似,但我要说的是“安全性高于便利性”。TryUpdateModel将忽略任何异常,如果出现问题,将返回false。UpdateModel将允许抛出异常。嗯,有趣的答案。关于在我的应用程序中使用automapper,我想已经很久了。顺便说一句,在大型模型中,我也使用viewmodels。这种方法不解决过度发布攻击。@UserControl,实际上它解决了它,因为视图模型将只包含用户允许修改的属性(视图中有输入字段的属性)。AutoMapper的
Map
方法将只更新域模型上的那些属性,其他属性保持不变,从而解决了如果您直接使用域模型,应用程序可能会遇到的批量分配漏洞。谢谢您的回答。有趣的解决方案。我还应该提到,对于模型验证,如果有聚合类(由其他类组成的类)使用[Required]之类的标记,则不会完全正常工作。我通常制作自己的模型状态检查器,并用调用布尔方法检查细节来替换if(!ModelState.IsValid())。