2010-04-21 60 views
1

嚴重的n00b警告在這裏;請憐憫!ASP.NET MVC:如何使用Html.ValidationSummary向最終用戶解釋無效類型違規?

因此,我完成了Nerd Dinner MVC Tutorial,現在我正在使用Nerd Dinner程序將VB.NET應用程序轉換爲ASP.NET MVC,作爲一種粗略模板。

我使用「的IsValid/GetRuleViolations()」的圖案來識別無效用戶輸入或違反業務規則的值。我正在使用LINQ to SQL,並利用「OnValidate()」鉤子,該鉤子允許我在嘗試通過CustomerRepository類保存對數據庫的更改時運行驗證並拋出應用程序異常。

總之,一切正常,只是在時間的形式值達到我的驗證方法無效的類型已經被轉換爲默認或現有的值。 (我有一個「StreetNumber」屬性是一個整數,但我想這對DateTime或任何其他非字符串也是一個問題。)

現在,我猜測UpdateModel()方法會拋出一個異常,然後更改值,因爲Html.ValidationMessage顯示在StreetNumber字段旁邊,但我的驗證方法從未看到原始輸入。有兩個問題:

  1. 雖然Html.ValidationMessage做信號,什麼是錯,沒有在Html.ValidationSummary沒有相應的條目。如果我甚至可以讓異常信息顯示在那裏,表明一個無效的投射或者什麼都比沒有好。

    駐留在我的客戶部分類
  2. 我的驗證方法永遠看不到原來的用戶輸入,所以我不知道,如果問題是缺少條目或無效的類型。我無法弄清楚如何讓我的驗證邏輯在一個地方保持良好和整潔,並仍然可以訪問表單值。

我當然可以在視圖中編寫一些邏輯來處理用戶輸入,但這看起來與我應該用MVC做的事情完全相反。

我需要一個新的驗證模式或者是有一些方法,以原來的形式值傳遞給處理我的模型類?


CustomerController代碼

// POST: /Customers/Edit/[id] 
    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Edit(int id, FormCollection formValues) 
    { 
     Customer customer = customerRepository.GetCustomer(id); 

     try 
     { 
      UpdateModel(customer); 

      customerRepository.Save(); 

      return RedirectToAction("Details", new { id = customer.AccountID }); 
     } 
     catch 
     { 
      foreach (var issue in customer.GetRuleViolations()) 
       ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage); 
     } 
     return View(customer); 
    } 

回答

2

這將是一個很好的起點:Scott Gu - ASP.NET MVC 2: Model Validation

但我認爲它是不好的做法,數據綁定的東西到你的域對象。

我個人的做法是使用POCODataAnnotations validation attributes相關的演示模型進行驗證(這可以使得稍後掛鉤客戶端驗證變得容易)。您也可以創建自己的ValidationAttributes來掛鉤數據綁定驗證。

如果它是數據綁定到你的POCO對象後,有效的,通過它,做你的更復雜的業務驗證服務。驗證通過後,將它傳遞給另一個服務(或相同的服務),將值傳遞給您的域對象,然後保存它。

我對Linq to SQL GetRuleViolations模式並不熟悉,所以隨時用適合的模式替換我的一個步驟即可。

我會盡我所能在這裏解釋它。

POCO演示模式:

public class EditCustomerForm 
{ 
    [DisplayName("First name")] 
    [Required(ErrorMessage = "First name is required")] 
    [StringLength(60, ErrorMessage = "First name cannot exceed 60 characters.")] 
    public string FirstName { get; set; } 

    [DisplayName("Last name")] 
    [Required(ErrorMessage = "Last name is required")] 
    [StringLength(60, ErrorMessage = "Last name cannot exceed 60 characters.")] 
    public string LastName { get; set; } 

    [Required(ErrorMessage = "Email is required")] 
    [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" + 
         @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" + 
         @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", 
         ErrorMessage = "Email appears to be invalid.")] 
    public string Email { get; set; } 
} 

控制器邏輯

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(int id, EditCustomerForm editCustomerForm) 
{ 
    var editCustomerForm = CustomerService.GetEditCustomerForm(id); 

    return View(editCustomerForm); 
} 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(int id, EditCustomerForm editCustomerForm) 
{ 
    try 
    { 
     if (Page.IsValid) 
     { 
      //Complex business validation that validation attributes can't handle 
      //If there is an error, I get this method to throw an exception that has 
      //the errors in it in the form of a IDictionary<string, string> 
      CustomerService.ValidateEditCustomerForm(editCustomerForm, id); 

      //If the above method hasn't thrown an exception, we can save it 
      //In this method you should map the editCustomerForm back to your Cusomter domain model 
      CustomerService.SaveCustomer(editCustomerForm, id) 

      //Now we can redirect 
      return RedirectToAction("Details", new { id = customer.AccountID }); 
    } 
    //ServiceLayerException is a custom exception thrown by 
    //CustomerService.ValidateEditCusotmerForm or possibly .SaveCustomer 
    catch (ServiceLayerException ex) 
    { 
     foreach (var kvp in ex.Errors) 
      ModelState.AddModelError(kvp.Key, kvp.Value); 
    } 
    catch (Exception ex) //General catch 
    { 
     ModelState.AddModelError("*", "There was an error trying to save the customer, please try again."); 
    } 

    return View(editCustomerForm); 
} 

清除泥?如果你需要更多的澄清,請讓我知道:-)

再次,這只是我的做法。你可能只是按照斯科特顧的文章,我先鏈接到,然後從那裏去。

HTHS,
查爾斯

+0

哇感謝詳細的答覆!這需要我花一段時間來解析,但我一定會在沉浸於自己之後再回來看看。謝謝! – 2010-04-21 23:57:37

+0

您的帖子是一個巨大的幫助!感謝您指點我正確的方向! – 2010-04-24 01:49:00

+0

很樂意提供幫助:-) – Charlino 2010-04-24 01:51:06

相關問題