稳扎稳打Silverlight(59) - 4.0通信之WCF RIA Services: 数据验证
稳扎稳打Silverlight(59) - 4.0通信之WCF RIA Services: 数据验证
作者:webabcd
介绍
Silverlight 4.0 之 WCF RIA Services:数据验证
在线DEMO
http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html
示例
演示在 WCF RIA Services 框架中实现数据验证的各种方法
1、服务端
MyDomainService.cs
代码
/*
* 一个 Domain Service 服务
*/
namespace Silverlight40.Web.Service
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using Silverlight40.Web.Model;
/*
* 用 LinqToEntities 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>;用 LinqToSql 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>
* Domain Service 内所有对客户端可见的方法都应该是 public 的,Domain Service 内的方法不支持重载
* 对客户端可见的方法要满足命名约定,或为其指定对应的 Attribute。当前支持 6 种数据操作:Query, Update, Insert, Delete, Invoke, Named Update, 详见文档
*
* [EnableClientAccess()] - 该类对客户端可见
* [EnableClientAccess(RequiresSecureEndpoint = true)] - 使用 HTTPS 协议
* [Ignore] - 指定的方法不作为服务而公开
* [Query(IsComposable=true)] - 支持客户端的 linq 查询,而且此查询会被在服务端执行
*
* 在多个 Domain Services 间共享实体:通过 [ExternalReference], [Association()], Context.AddReference() 实现,详见文档
*/
// 服务端的类名为:MyDomainService,则其生成的客户端上下文的类名为:MyDomainContext
[EnableClientAccess()]
public class MyDomainService : LinqToEntitiesDomainService<NorthwindEntities>
{
[Query(IsDefault = true)]
public IQueryable<Category> GetCategories()
{
return this.ObjectContext.Categories;
}
public void InsertCategory(Category category)
{
if ((category.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(category, EntityState.Added);
}
else
{
this.ObjectContext.Categories.AddObject(category);
}
}
public void UpdateCategory(Category currentCategory)
{
this.ObjectContext.Categories.AttachAsModified(currentCategory, this.ChangeSet.GetOriginal(currentCategory));
}
public void DeleteCategory(Category category)
{
if ((category.EntityState == EntityState.Detached))
{
this.ObjectContext.Categories.Attach(category);
}
this.ObjectContext.Categories.DeleteObject(category);
}
[Query(IsDefault = true)]
public IQueryable<Product> GetProducts()
{
return this.ObjectContext.Products;
}
public IQueryable<Product> GetProductsBySort(string sort)
{
return ObjectContext.Products.OrderBy(sort);
}
public void InsertProduct(Product product)
{
if ((product.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
}
else
{
this.ObjectContext.Products.AddObject(product);
}
}
public void UpdateProduct(Product currentProduct)
{
this.ObjectContext.Products.AttachAsModified(currentProduct, this.ChangeSet.GetOriginal(currentProduct));
}
public void DeleteProduct(Product product)
{
if ((product.EntityState == EntityState.Detached))
{
this.ObjectContext.Products.Attach(product);
}
this.ObjectContext.Products.DeleteObject(product);
}
public IQueryable<Product> GetProductsByCategoryId(int categoryId)
{
return this.ObjectContext.Products.Where(p => p.CategoryID == categoryId);
}
}
}
* 一个 Domain Service 服务
*/
namespace Silverlight40.Web.Service
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using Silverlight40.Web.Model;
/*
* 用 LinqToEntities 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>;用 LinqToSql 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>
* Domain Service 内所有对客户端可见的方法都应该是 public 的,Domain Service 内的方法不支持重载
* 对客户端可见的方法要满足命名约定,或为其指定对应的 Attribute。当前支持 6 种数据操作:Query, Update, Insert, Delete, Invoke, Named Update, 详见文档
*
* [EnableClientAccess()] - 该类对客户端可见
* [EnableClientAccess(RequiresSecureEndpoint = true)] - 使用 HTTPS 协议
* [Ignore] - 指定的方法不作为服务而公开
* [Query(IsComposable=true)] - 支持客户端的 linq 查询,而且此查询会被在服务端执行
*
* 在多个 Domain Services 间共享实体:通过 [ExternalReference], [Association()], Context.AddReference() 实现,详见文档
*/
// 服务端的类名为:MyDomainService,则其生成的客户端上下文的类名为:MyDomainContext
[EnableClientAccess()]
public class MyDomainService : LinqToEntitiesDomainService<NorthwindEntities>
{
[Query(IsDefault = true)]
public IQueryable<Category> GetCategories()
{
return this.ObjectContext.Categories;
}
public void InsertCategory(Category category)
{
if ((category.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(category, EntityState.Added);
}
else
{
this.ObjectContext.Categories.AddObject(category);
}
}
public void UpdateCategory(Category currentCategory)
{
this.ObjectContext.Categories.AttachAsModified(currentCategory, this.ChangeSet.GetOriginal(currentCategory));
}
public void DeleteCategory(Category category)
{
if ((category.EntityState == EntityState.Detached))
{
this.ObjectContext.Categories.Attach(category);
}
this.ObjectContext.Categories.DeleteObject(category);
}
[Query(IsDefault = true)]
public IQueryable<Product> GetProducts()
{
return this.ObjectContext.Products;
}
public IQueryable<Product> GetProductsBySort(string sort)
{
return ObjectContext.Products.OrderBy(sort);
}
public void InsertProduct(Product product)
{
if ((product.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
}
else
{
this.ObjectContext.Products.AddObject(product);
}
}
public void UpdateProduct(Product currentProduct)
{
this.ObjectContext.Products.AttachAsModified(currentProduct, this.ChangeSet.GetOriginal(currentProduct));
}
public void DeleteProduct(Product product)
{
if ((product.EntityState == EntityState.Detached))
{
this.ObjectContext.Products.Attach(product);
}
this.ObjectContext.Products.DeleteObject(product);
}
public IQueryable<Product> GetProductsByCategoryId(int categoryId)
{
return this.ObjectContext.Products.Where(p => p.CategoryID == categoryId);
}
}
}
MyDomainService.metadata.cs
代码
/*
* [MetadataTypeAttribute()] - 指定类的元数据对象
* [Include] - 生成的客户端上下文包含此字段
* [Exclude] - 生成的客户端上下文不包含此字段
* [Composition] - 指定字段为关联数据,即父实体增删改查时,此关联数据也会做相应的变化。指定此 Attribute 后,需显式指定其为 [Include]
* 注:如果使用 DomainDataSource 则不能将字段设置为 [Composition]
* [Editable(true)], [Editable(false)] - 指定字段是否可编辑
*
* 支持 Data Annotation 方式的数据验证:DataTypeAttribute(具有很多常用的数据类型的验证), RangeAttribute, RegularExpressionAttribute, RequiredAttribute, StringLengthAttribute 等
* 注:如果需要将自定义的验证既作用于服务端又作用于客户端,则需要把自定义的验证逻辑代码设置为 shared 模式
*/
namespace Silverlight40.Web.Model
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using Silverlight40.Web.Service.Validation;
[MetadataTypeAttribute(typeof(Category.CategoryMetadata))]
[CustomValidation(typeof(CategoryValidator), "ValidateCategory")] // 演示通过自定义的实体验证器来实现验证
public partial class Category
{
internal sealed class CategoryMetadata
{
private CategoryMetadata()
{
}
[Key()]
public int CategoryID { get; set; }
[Display(Name = "类别名称")] // 显示用
[Numeric(ErrorMessage = "字段“{0}”必须是数字")] // 演示通过继承 RegularExpressionAttribute 实现字段的自定义验证
[StartsWith(ErrorMessage = "{0}")] // 演示通过继承 ValidationAttribute 实现字段的自定义验证
[CustomValidation(typeof(EndsWidthValidator), "ValidateCategoryName")] // 演示通过自定义的字段验证器来实现验证
public string CategoryName { get; set; }
public string Description { get; set; }
[Exclude]
public byte[] Picture { get; set; }
[Include]
[Composition]
public EntityCollection<Product> Products { get; set; }
}
}
[MetadataTypeAttribute(typeof(Product.ProductMetadata))]
public partial class Product
{
internal sealed class ProductMetadata
{
private ProductMetadata()
{
}
public Category Category { get; set; }
public Nullable<int> CategoryID { get; set; }
public bool Discontinued { get; set; }
public EntityCollection<Order_Detail> Order_Details { get; set; }
[Display(Order = 0, Name = "产品ID")]
public int ProductID { get; set; }
[Display(Order = 1, Name = "产品名称")]
public string ProductName { get; set; }
public string QuantityPerUnit { get; set; }
public Nullable<short> ReorderLevel { get; set; }
public Supplier Supplier { get; set; }
public Nullable<int> SupplierID { get; set; }
public Nullable<decimal> UnitPrice { get; set; }
public Nullable<short> UnitsInStock { get; set; }
public Nullable<short> UnitsOnOrder { get; set; }
}
}
}
* [MetadataTypeAttribute()] - 指定类的元数据对象
* [Include] - 生成的客户端上下文包含此字段
* [Exclude] - 生成的客户端上下文不包含此字段
* [Composition] - 指定字段为关联数据,即父实体增删改查时,此关联数据也会做相应的变化。指定此 Attribute 后,需显式指定其为 [Include]
* 注:如果使用 DomainDataSource 则不能将字段设置为 [Composition]
* [Editable(true)], [Editable(false)] - 指定字段是否可编辑
*
* 支持 Data Annotation 方式的数据验证:DataTypeAttribute(具有很多常用的数据类型的验证), RangeAttribute, RegularExpressionAttribute, RequiredAttribute, StringLengthAttribute 等
* 注:如果需要将自定义的验证既作用于服务端又作用于客户端,则需要把自定义的验证逻辑代码设置为 shared 模式
*/
namespace Silverlight40.Web.Model
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using Silverlight40.Web.Service.Validation;
[MetadataTypeAttribute(typeof(Category.CategoryMetadata))]
[CustomValidation(typeof(CategoryValidator), "ValidateCategory")] // 演示通过自定义的实体验证器来实现验证
public partial class Category
{
internal sealed class CategoryMetadata
{
private CategoryMetadata()
{
}
[Key()]
public int CategoryID { get; set; }
[Display(Name = "类别名称")] // 显示用
[Numeric(ErrorMessage = "字段“{0}”必须是数字")] // 演示通过继承 RegularExpressionAttribute 实现字段的自定义验证
[StartsWith(ErrorMessage = "{0}")] // 演示通过继承 ValidationAttribute 实现字段的自定义验证
[CustomValidation(typeof(EndsWidthValidator), "ValidateCategoryName")] // 演示通过自定义的字段验证器来实现验证
public string CategoryName { get; set; }
public string Description { get; set; }
[Exclude]
public byte[] Picture { get; set; }
[Include]
[Composition]
public EntityCollection<Product> Products { get; set; }
}
}
[MetadataTypeAttribute(typeof(Product.ProductMetadata))]
public partial class Product
{
internal sealed class ProductMetadata
{
private ProductMetadata()
{
}
public Category Category { get; set; }
public Nullable<int> CategoryID { get; set; }
public bool Discontinued { get; set; }
public EntityCollection<Order_Detail> Order_Details { get; set; }
[Display(Order = 0, Name = "产品ID")]
public int ProductID { get; set; }
[Display(Order = 1, Name = "产品名称")]
public string ProductName { get; set; }
public string QuantityPerUnit { get; set; }
public Nullable<short> ReorderLevel { get; set; }
public Supplier Supplier { get; set; }
public Nullable<int> SupplierID { get; set; }
public Nullable<decimal> UnitPrice { get; set; }
public Nullable<short> UnitsInStock { get; set; }
public Nullable<short> UnitsOnOrder { get; set; }
}
}
}
StartsWithAttribute.shared.cs
代码
/*
* 验证规则:“必须以 1 开头”
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace Silverlight40.Web.Service.Validation
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class StartsWithAttribute : ValidationAttribute
{
private readonly string _param;
/*
/// <summary>
/// 构造函数
/// 如果使用 shared 方式,则对于客户端来说不支持构造函数传参(服务端还是支持的)
/// </summary>
/// <param name="param">指定的开头字符串</param>
public StartsWithAttribute(string param)
{
_param = param;
}
*/
public StartsWithAttribute()
{
_param = "1";
}
/// <summary>
/// 指定的值是否可以通过验证
/// </summary>
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var boolean = value.ToString().StartsWith(this._param);
if (boolean)
return ValidationResult.Success;
else
// new string[] { validationContext.MemberName } - 要对应到相关的 name 上,这样客户端才会有正确的验证提示效果
return new ValidationResult("必须以 1 开头", new string[] { validationContext.MemberName });
}
}
}
* 验证规则:“必须以 1 开头”
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace Silverlight40.Web.Service.Validation
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class StartsWithAttribute : ValidationAttribute
{
private readonly string _param;
/*
/// <summary>
/// 构造函数
/// 如果使用 shared 方式,则对于客户端来说不支持构造函数传参(服务端还是支持的)
/// </summary>
/// <param name="param">指定的开头字符串</param>
public StartsWithAttribute(string param)
{
_param = param;
}
*/
public StartsWithAttribute()
{
_param = "1";
}
/// <summary>
/// 指定的值是否可以通过验证
/// </summary>
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var boolean = value.ToString().StartsWith(this._param);
if (boolean)
return ValidationResult.Success;
else
// new string[] { validationContext.MemberName } - 要对应到相关的 name 上,这样客户端才会有正确的验证提示效果
return new ValidationResult("必须以 1 开头", new string[] { validationContext.MemberName });
}
}
}
EndsWidthValidator.shared.cs
代码
/*
* 验证规则:“CategoryName 必须以 1 结尾”,用于验证字段的验证器
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace Silverlight40.Web.Service.Validation
{
public class EndsWidthValidator
{
public static ValidationResult ValidateCategoryName(string s, ValidationContext context)
{
ValidationResult result = ValidationResult.Success;
if (s.EndsWith("1"))
result = ValidationResult.Success;
else
// new string[] { context.MemberName } - 要对应到相关的 name 上,这样客户端才会有正确的验证提示效果
result = new ValidationResult("必须以 1 结尾", new string[] { "CategoryName" });
return result;
}
}
}
* 验证规则:“CategoryName 必须以 1 结尾”,用于验证字段的验证器
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace Silverlight40.Web.Service.Validation
{
public class EndsWidthValidator
{
public static ValidationResult ValidateCategoryName(string s, ValidationContext context)
{
ValidationResult result = ValidationResult.Success;
if (s.EndsWith("1"))
result = ValidationResult.Success;
else
// new string[] { context.MemberName } - 要对应到相关的 name 上,这样客户端才会有正确的验证提示效果
result = new ValidationResult("必须以 1 结尾", new string[] { "CategoryName" });
return result;
}
}
}
NumericAttribute.shared.cs
代码
/*
* 验证规则:“必须是数字”
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace Silverlight40.Web.Service.Validation
{
public class NumericAttribute : RegularExpressionAttribute
{
public NumericAttribute()
: base("^[0-9]*$")
{
}
/// <summary>
/// 格式化错误信息
/// </summary>
/// <param name="name">指定的字段名</param>
/// <returns></returns>
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name);
}
}
}
* 验证规则:“必须是数字”
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
namespace Silverlight40.Web.Service.Validation
{
public class NumericAttribute : RegularExpressionAttribute
{
public NumericAttribute()
: base("^[0-9]*$")
{
}
/// <summary>
/// 格式化错误信息
/// </summary>
/// <param name="name">指定的字段名</param>
/// <returns></returns>
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name);
}
}
}
CategoryValidator.shared.cs
代码
/*
* 验证规则:“CategoryName 必须包含 3”,用于验证实体的验证器
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using Silverlight40.Web.Model;
namespace Silverlight40.Web.Service.Validation
{
public class CategoryValidator
{
public static ValidationResult ValidateCategory(Category category, ValidationContext context)
{
ValidationResult result = ValidationResult.Success;
if (category.CategoryName.Contains("3"))
result = ValidationResult.Success;
else
// new string[] { context.MemberName } - 要对应到相关的 name 上,这样客户端才会有正确的验证提示效果
result = new ValidationResult("必须包含 3", new string[] { "CategoryName" });
return result;
}
}
}
* 验证规则:“CategoryName 必须包含 3”,用于验证实体的验证器
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using Silverlight40.Web.Model;
namespace Silverlight40.Web.Service.Validation
{
public class CategoryValidator
{
public static ValidationResult ValidateCategory(Category category, ValidationContext context)
{
ValidationResult result = ValidationResult.Success;
if (category.CategoryName.Contains("3"))
result = ValidationResult.Success;
else
// new string[] { context.MemberName } - 要对应到相关的 name 上,这样客户端才会有正确的验证提示效果
result = new ValidationResult("必须包含 3", new string[] { "CategoryName" });
return result;
}
}
}
2、客户端
ValidationDemo.xaml
代码
<navigation:Page x:Class="Silverlight40.WCFRIAServices.ValidationDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:ns="clr-namespace:Silverlight40.WCFRIAServices"
Title="ValidationDemo Page">
<Grid x:Name="LayoutRoot">
<StackPanel HorizontalAlignment="Left" DataContext="{Binding .}">
<!--
用于显示验证错误列表
-->
<sdk:ValidationSummary Margin="3">
<sdk:ValidationSummary.Header>
错误列表:
</sdk:ValidationSummary.Header>
</sdk:ValidationSummary>
<!--
ValidatesOnDataErrors - 指定是否绑定数据实体上的 IDataErrorInfo 实现的验证错误
ValidatesOnNotifyDataErrors - 指定是否绑定数据实体上的 INotifyDataErrorInfo 实现的验证错误
ValidatesOnExceptions - 指定当出现异常时,是否报告验证错误
NotifyOnValidationError - 指定出现验证错误时是否引发 BindingValidationError 事件
-->
<StackPanel Orientation="Horizontal">
<TextBlock Name="lblCategoryName" Text="产品类别名称:" />
<TextBox Name="txtCategoryName" Text="{Binding Path=CategoryName, Mode=TwoWay, ValidatesOnDataErrors=True, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True, ValidatesOnExceptions=True}" />
<sdk:Label Target="{Binding ElementName=txtCategoryName}" />
<sdk:DescriptionViewer Description="必须是数字;必须以 1 开头;必须以 1 结尾;必须包含 3" />
</StackPanel>
<!--
单击按钮后看验证提示效果
-->
<Button Name="btnAdd" Content="新增" Click="btnAdd_Click" />
</StackPanel>
</Grid>
</navigation:Page>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:ns="clr-namespace:Silverlight40.WCFRIAServices"
Title="ValidationDemo Page">
<Grid x:Name="LayoutRoot">
<StackPanel HorizontalAlignment="Left" DataContext="{Binding .}">
<!--
用于显示验证错误列表
-->
<sdk:ValidationSummary Margin="3">
<sdk:ValidationSummary.Header>
错误列表:
</sdk:ValidationSummary.Header>
</sdk:ValidationSummary>
<!--
ValidatesOnDataErrors - 指定是否绑定数据实体上的 IDataErrorInfo 实现的验证错误
ValidatesOnNotifyDataErrors - 指定是否绑定数据实体上的 INotifyDataErrorInfo 实现的验证错误
ValidatesOnExceptions - 指定当出现异常时,是否报告验证错误
NotifyOnValidationError - 指定出现验证错误时是否引发 BindingValidationError 事件
-->
<StackPanel Orientation="Horizontal">
<TextBlock Name="lblCategoryName" Text="产品类别名称:" />
<TextBox Name="txtCategoryName" Text="{Binding Path=CategoryName, Mode=TwoWay, ValidatesOnDataErrors=True, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True, ValidatesOnExceptions=True}" />
<sdk:Label Target="{Binding ElementName=txtCategoryName}" />
<sdk:DescriptionViewer Description="必须是数字;必须以 1 开头;必须以 1 结尾;必须包含 3" />
</StackPanel>
<!--
单击按钮后看验证提示效果
-->
<Button Name="btnAdd" Content="新增" Click="btnAdd_Click" />
</StackPanel>
</Grid>
</navigation:Page>
ValidationDemo.xaml.cs
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using Silverlight40.Web.Service;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Client;
using Silverlight40.Web.Model;
namespace Silverlight40.WCFRIAServices
{
public partial class ValidationDemo : Page
{
MyDomainContext _context = new MyDomainContext();
public ValidationDemo()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
Category category = new Category();
category.CategoryName = txtCategoryName.Text;
this.DataContext = category;
// 为实体添加验证错误信息
List<ValidationResult> validationResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(this.DataContext, new ValidationContext(this.DataContext, null, null), validationResults))
{
Entity entity = (Entity)this.DataContext;
foreach (var item in validationResults)
{
entity.ValidationErrors.Add(item);
}
}
// 如果发现验证错误则。。。(客户端)
if (category.HasValidationErrors)
{
foreach (ValidationResult result in category.ValidationErrors)
{
string error = string.Format("属性 [{0}] 验证出错 [{1}]", result.MemberNames.First(), result.ErrorMessage);
MessageBox.Show(error, "Error", MessageBoxButton.OK);
}
this.DataContext = category;
}
else
{
_context.Categories.Add(category);
_context.SubmitChanges(OnSubmitCompleted, category);
}
}
private void OnSubmitCompleted(SubmitOperation so)
{
if (so.HasError)
{
MessageBox.Show(so.Error.ToString());
so.MarkErrorAsHandled();
// 如果发现验证错误则。。。(服务端)
if (so.EntitiesInError.Any())
{
foreach (ValidationResult result in so.EntitiesInError.First().ValidationErrors)
{
string error = string.Format("属性 [{0}] 验证出错 [{1}]", result.MemberNames.First(), result.ErrorMessage);
MessageBox.Show(error, "Error", MessageBoxButton.OK);
}
this.DataContext = so.UserState as Category;
}
}
else
{
MessageBox.Show("添加成功");
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using Silverlight40.Web.Service;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Client;
using Silverlight40.Web.Model;
namespace Silverlight40.WCFRIAServices
{
public partial class ValidationDemo : Page
{
MyDomainContext _context = new MyDomainContext();
public ValidationDemo()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
Category category = new Category();
category.CategoryName = txtCategoryName.Text;
this.DataContext = category;
// 为实体添加验证错误信息
List<ValidationResult> validationResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(this.DataContext, new ValidationContext(this.DataContext, null, null), validationResults))
{
Entity entity = (Entity)this.DataContext;
foreach (var item in validationResults)
{
entity.ValidationErrors.Add(item);
}
}
// 如果发现验证错误则。。。(客户端)
if (category.HasValidationErrors)
{
foreach (ValidationResult result in category.ValidationErrors)
{
string error = string.Format("属性 [{0}] 验证出错 [{1}]", result.MemberNames.First(), result.ErrorMessage);
MessageBox.Show(error, "Error", MessageBoxButton.OK);
}
this.DataContext = category;
}
else
{
_context.Categories.Add(category);
_context.SubmitChanges(OnSubmitCompleted, category);
}
}
private void OnSubmitCompleted(SubmitOperation so)
{
if (so.HasError)
{
MessageBox.Show(so.Error.ToString());
so.MarkErrorAsHandled();
// 如果发现验证错误则。。。(服务端)
if (so.EntitiesInError.Any())
{
foreach (ValidationResult result in so.EntitiesInError.First().ValidationErrors)
{
string error = string.Format("属性 [{0}] 验证出错 [{1}]", result.MemberNames.First(), result.ErrorMessage);
MessageBox.Show(error, "Error", MessageBoxButton.OK);
}
this.DataContext = so.UserState as Category;
}
}
else
{
MessageBox.Show("添加成功");
}
}
}
}
OK
[源码下载]