2011-09-19 38 views
2

我對使用問題的「最佳實踐」控制器感到有點困惑。asp.net mvc控制器發佈最佳實踐

我通常代碼看起來

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」或簡單的電話Model.IsValid是好主意,趕上例外控制器?

感謝

+2

TryUpdateModel將吞下任何異常,並在出現問題時返回false。 UpdateModel將允許拋出異常。 – jrummell

回答

0

這取決於您是否期望並計劃處理異常。

我通常的做法是:

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"); 
} 

我嘗試使用所有的人都在我的代碼,試圖抓住每一個問題,它打破了之前的東西。

+0

感謝您的回答。有趣的解決方案。 – Mennion

+0

不用擔心。我希望它適合你。 –

+0

我還應該提到,對於模型驗證,如果您有聚合類(由其他類構成的類)使用[必需]標籤,那麼不要一切順利。我通常會創建自己的模型狀態檢查器,並用(!ModelState.IsValid())調用布爾方法來檢查特定情況。 –

5

下面是我比較喜歡的另一種方式:

[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"); 
} 

所以,你可以看到沒有FormCollection,沒有TryUpdateModel,沒有UpdateModel,沒有try/catch

+0

嗯,有趣的答案。在我的應用程序中使用automapper我想很長一段時間。順便說一句,在大型模型中,我也使用視圖模型。 – Mennion

+0

該方法沒有解決發佈攻擊問題。 – UserControl

+0

@UserControl,實際上它確實解決了這個問題,因爲視圖模型將只包含用戶可修改的屬性*(在視圖中有輸入字段的屬性)。 AutoMapper的Map方法將只更新領域模型上的屬性,使其他屬性保持不變,從而解決如果直接使用領域模型時應用程序遭受的質量分配漏洞。 –

0

我認爲您應該始終使用視圖模型而不是formcollection來避免發佈不足和過度發佈問題。因此,在我看來,最佳實踐是使用視圖模型來呈現視圖,以及一種post/get模型,它與您希望用戶發佈到/從某個操作獲取的內容完全綁定。

這可能是一些額外的工作,並且一些視圖模型看起來與您在控制器操作中用於綁定的模型非常相似,但我會說「安全性過於方便」。