2010-04-21 18 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

相关问题