现在的位置: 首页 > 综合 > 正文

ASP.NET MVC Part.4(Validation、ActionResult)

2012年08月22日 ⁄ 综合 ⁄ 共 3853字 ⁄ 字号 评论关闭
文章目录

       整理好 Edit.aspx 试图后,应该考虑要为用户的输入增加验证。从数据模型可以获得部分支持。如果用户给某个数值类型的字段输入了字符串,他会看到一个错误页面,可能是默认的 ASP.NET 栈信息或者自定义错误页面(如果在控制器和应用程序中启用了自定义错误处理)。

       绝大部分用户都不能够通过栈追踪信息知道自己输入了非法的值,并且他们也不应该知道,这就是为什么 MVC 框架内置了某些强大的验证功能

 

执行基本的验证

       MVC 框架使数据从客户端回发到控制器时的错误验证检查变得非常简单。我们修改了 Edit 方法获取用户数据的签名,这样 MVC 框架就会通过表单的值自动创建 ProductListWrapper 的实例

       通过 ModelState.IsValid 方法检查验证错误,如果有问题,及时从方法中返回,指定把传给 Edit 方法的 ProductListWrapper 实例使用 Edit 视图显示。要注意的是,这里再次把供应商和类别名作为视图数据的一部分,这是因为 Edit.aspx 依赖于这些数据来呈现,如果没有这些就会抛出一个异常

public ActionResult Edit(int id, ProductListWrapper pwrap)

{

    try

    {

        if (!ModelState.IsValid)

        {

            ViewData["categories"] = nwa.GetAllCategories();

            ViewData["suppliers"] = nwa.GetAllSuppliers();

            return View("Edit", pwrap);

        }

 

        Products prod = nwa.GetProduct(id);

        if (prod != null)

        {

            ProductListWrapper wrapper = new ProductListWrapper()

            {

                product = prod

            };

            UpdateModel(wrapper);

            prod.SupplierID = nwa.GetSupplierID(wrapper.SelectedSupplier);

            prod.CategoryID = nwa.GetCategoryID(wrapper.SelectedCategory);

            nwa.SaveChanges();

            return RedirectToAction("Index");

        }

        else

        {

            throw new NoSuchRecordException();

        }

    }

    catch

    {

        return View();

    }

}

       还需要在 Edit.aspx 里添加一行代码以享用验证支持带来的便利:

......

<legend>Edit Product Details</legend>

 

<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>

......

       现在如果尝试输入一些非法数据,可以看见如下效果(产生问题的输入框也高亮显示着):

image

 

       如果要把验证提醒消息放在数据字段的旁边,可以使用 ValidationMessageFor 辅助方法,它为指定的数据项生成验证警告。例如,下边是被应用到 RecordLevel 字段的辅助方法:

<tr>

    <td>Reorder Level:</td>

    <td>

        <%: Html.TextBoxFor(e => e.product.ReorderLevel)%>

        <%: Html.ValidationMessageFor(e => e.product.ReorderLevel) %>

    </td>

</tr>

image

 

增加验证标注

       MVC 框架支持验证的元数据标注,它让你能使用标准的标注强制通用的验证标准并自定义约束。可以通过部分类的功能把元数据类和数据模型类关联到一起,然后对之应用 C# 标注

       直观一点,这个元数据类为 Product 模型数据类型的 UnitInStock 属性应用一系列的验证检查,Product 模型数据类型是在 Models 项目目录里创建的:

using System.ComponentModel.DataAnnotations;

 

namespace BasicMvcApplication.Models

{

    // MetadataType 指定用 ProductsMetaData 类保存 Products 类的元数据

    [MetadataType(typeof(ProductsMetaData))]

    public partial class Products // 分布类与实体框架数据模型产生的类具有相同的签名

    {

        public class ProductsMetaData

        {

            // 为要验证的字段定义相同名称的属性,类型并不需要对应,元数据系统基于成员名称工作

            // 添加了 Range 特性

            [Range(1, 50)]

            public object UnitsInStock { get; set; } 

        }

    }

}

       这非常不直观,但先记住这些,对于每个要标注的数据模型类型都只要做一次就可以了。

       现在,如果编辑超出范围的值就会产生一个错误,如图:

image

       验证属性在 System.ComponentModel.DataAnnotations 命名空间中。我们已经使用了 RangeAttribute,另外还有些属性较为常用:StringLengthAttributeRegularExpressionAttributeRequiredAttributeDataTypeAttribute 等。

       还可以从 ValidationAttribute 类继承以创建自定义的验证属性!下面的属性确保数值要么是偶数,要么是奇数:

using System.ComponentModel.DataAnnotations;

 

namespace BasicMvcApplication.Models

{

    public class OddOrEvenAttribute : ValidationAttribute

    {

        public Mode mode { get; set; }

        public OddOrEvenAttribute(Mode m)

        {

            mode = m;

        }

 

        public override bool IsValid(object value)

        {

            try

            {

                if (int.Parse(value.ToString()) % 2 == 0)

                {

                    return mode == Mode.Even;

                }

                else

                {

                    return mode == Mode.Odd;

                }

            }

            catch

            {

                return false;

            }

        }

 

        public enum Mode

        {

            Odd,

            Even

        }

    }

}

       当属性应用的数据模型字段被提交数据时,MVC 框架会调用 IsValid 方法来检查字段值的合法性。下面是通过元数据类被应用到 UnitsInStock 的自定义属性:

[Range(1, 50)]

[OddOrEven(OddOrEvenAttribute.Mode.Even, 

    ErrorMessage = "Units In Stock must be even.")]

public object UnitsInStock { get; set; }

       现在,如果提交了不合适的值可以看到如下效果:

image

 

 

使用动作结果

       在控制器方法里,我们返回 View 方法的结果,或者在某种情况下返回 RedirectToAction 方法。这一小节我将解释这些方法的意义并演示如何通过它们控制 MVC 应用程序。

       MVC 框架要求所有控制器活动方法都返回 ActionResult 的实例,这样框架才能知道后续如何处理(为用户呈现视图、调用其他活动等)。为了让 MVC 程序员更轻松,微软还提供了一系列辅助方法,我们可以通过它们创建 ActionResult 的子类的实例以获得不同的效果。

       例如,为了告诉 MVC 框架为用户程序视图,我们返回 ViewResult 的实例(它是 ActionResult 的子类),用来创建 ViewResult 的辅助方法是 View(),这是我们一直大量使用它的原因。View 有一系列的重载,把某个对象作为唯一的参数传给 View,MVC 框架就会根据活动方法的名称来决定要使用的视图,并用它来显示传入的对象

       如果要返回另一个控制器方法的结果,可以使用 RedirectToAction 方法轻松创建 RedirectToRouteResult 类。下表是最有用的控制器辅助方法以及它们的返回类型:

辅助方法

ActionResult 子类

描  述

Views() ViewResult 呈现视图
RedirectToAction() RedirectResult 返回另一个控制器方法的结果
Json() JsonResult 使用 Json 序列化数据模型对象
JavaScript() JavaScriptResult 返回客户端要执行的脚本
FileResult() FileResult 返回文件的内容

 

返回 JSON 数据

       使用脚本 (包括 jQuery 编写的脚本) 时经常需要从模型返回 JSON 格式的数据。可以直接传递对象给 JSON 辅助方法来返回 JSON 数据,但在使用由实体框架或 LINQ to SQL 向导生成的数据模型类时还是要小心。自动生成的数据模型为了在不同表间进行导航而使用了循环引用,这对 JSON 注入器来说是一件相当痛苦的事情。因此我们给控制器新增加了一个活动方法,它以 JSON 格式输出产品的细节:

抱歉!评论已关闭.