我的silverlight解决方案有3个项目文件
元数据文件是具有相关数据注释验证的部分类。
[MetadataTypeAttribute(typeof(User.UserMetadata))]
public partial class User
{
[CustomValidation(typeof(UsernameValidator), "IsUsernameAvailable")]
public string UserName { get; set; }
}
现在我的问题是我需要保留此类UsernameValidator 如果我的Metadata类和edmx位于服务器端(Web),那么我知道我需要在我的web项目中创建一个.shared.cs类,然后添加适当的静态方法。
我的IsUserAvailable方法实习生将调用域服务方法作为asyc验证的一部分。
[Invoke]
public bool IsUsernameAvailable(string username)
{
return !Membership.FindUsersByName(username).Cast<MembershipUser>().Any();
}
如果我的元数据类与我的域服务所在的项目相同,那么我可以从我的UsernameValidator.Shared.cs类调用域服务方法。
但是我的实体模型和元数据都在单独的库中。
任何想法都将受到赞赏
杰夫奇妙地在这里解释了asyc验证 http://jeffhandley.com/archive/2010/05/26/asyncvalidation-again.aspx 但只有当您的模型,元数据和共享类都在服务器端时才会起作用。
答案 0 :(得分:1)
有一种黑客可以做到这一点。它不是一种干净的方式,但它可能会起作用。
因为.shared负责代码生成,所以它不会在代码的#if括号中抱怨某些编译错误。所以你可以做的是在任何项目中创建一个Validator.Shared.cs,并确保它生成到silverlight端。
添加以下代码。并且不要忘记命名空间。
#if SILVERLIGHT
using WebProject.Web.Services;
using System.ServiceModel.DomainServices.Client;
#endif
#if SILVERLIGHT
UserContext context = new UserContext();
InvokeOperation<bool> availability = context.DoesUserExist(username);
//code ommited. use what logic you want, maybe Jeffs post.
#endif
编译器将忽略此代码部分,因为它不符合if语句的条件。同时在Silverlight客户端,它尝试重新编译共享验证器,它满足if语句的条件。
像我说的那样。这不是一个干净的方法。您可能会遇到缺少名称空间的问题。您需要在非生成的Validator.shared.cs中解决它们,最后让它在Silverlight中工作。如果你这样做,你可以通过调用操作在silverlight中进行验证。但是在您的项目中不会出现与Jeff的帖子一样的模型和元数据。编辑:我发现了一种更清洁,更好的方法
您可以在silverlight客户端创建部分类并执行以下操作
public partial class User
{
partial void OnUserNameChanging(string value)
{
//must be new to check for this validation rule
if(EntityState == EntityState.New)
{
var ctx = new UserContext();
ctx.IsValidUserName(value).Completed += (s, args) =>
{
InvokeOperation invop = (InvokeOperation) s;
bool isValid = (bool) invop.Value;
if(!isValid)
{
ValidationResult error = new ValidationResult(
"Username already exists",
new string[] {"UserName"});
ValidationErrors.Add(error;
}
};
}
}
}
这是由WCF RIA Services生成的方法,可以轻松地进行部分分割,您可以像这样添加带外验证。这是一种更简洁的方法,但现在这种验证只存在于silverlight客户端。
希望这有帮助