如何在Metadata文件中设置Customvalidation,如果元数据位于不同的Model项目中

时间:2012-04-06 01:58:34

标签: wcf silverlight silverlight-4.0 wcf-ria-services ria

我的silverlight解决方案有3个项目文件

  1. Silverlight部分(客户端)
  2. Web部件(服务器)
  3. 实体模型(我在单独的项目中将元数据与元数据一起维护)
  4. 元数据文件是具有相关数据注释验证的部分类。

    [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 但只有当您的模型,元数据和共享类都在服务器端时才会起作用。

1 个答案:

答案 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客户端。

希望这有帮助