2

我在 Sitecore 中创建了一个自定义验证器。它正确执行,我可以调试它并逐步完成它。

我从 扩展了我的验证器StandardValidator,而它又从 扩展BaseValidator

在我的验证器中,我得到了这个项目:

var item = GetItem();

GetItem是一种来自 的方法BaseValidator。根据我的阅读,这是获得要验证的项目的标准方法。

问题:我返回的项目没有反映在 Content Editor 中编辑的值。相反,它似乎只是数据库中的项目(因此,它在内容编辑器中首次加载时的样子,没有反映可能对其进行的任何更改)。

因此,我无法验证。要验证编辑器可能在内容编辑器中更改的数据,我需要能够看到这些更改。现在查看该项目在数据库中的位置对我没有帮助。

我做了一些扩展调试,可能有用也可能没用——

我反编译了内核,并遍历了StandardValidatorBaseValidator.

from的GetItem方法BaseValidator做了我怀疑的事情——它从数据库中获取项目。但随后它通过一个名为的方法运行它,该方法UpdateItem似乎旨在将来自内容编辑器的输入值覆盖在存储的值之上(从而返回一个准确反映当前位于编辑器中的数据的对象)。这显然是我想要的。

但是,仅当被调用的属性具有值UpdateItem时才会覆盖任何内容......而且它永远不会。ControlToValidate我已经尝试将此验证器作为字段验证器和项目验证器。我通过保存一个项目和一个字段来启动它。我在 Visual Studio 中设置了一个断点并在ControlToValidate. 有一次(莫名其妙地)它的值是FIELD165901047(对应于内容编辑器中的字段 ID),但在所有其他情况下,它都是null.

这意味着UpdateItem实际上什么都不做,并且该项目只是返回,因为它当前位于数据库中,这无济于事——我试图在保存到数据库之前验证在内容编辑器中输入的值。

不管我的调查如何(我想我理解UpdateItem,但我承认我可能会误解它,并且我没有考虑潜在的反编译错误),我仍然有这个基本问题:

var item = GetItem();

这似乎永远不会从内容编辑器返回值。它直接从数据库返回项目,这对我没有帮助。

4

2 回答 2

0

在我的验证器(字段类型验证器)中,我使用过

 var field = this.GetField();

获取要验证的字段的新值。这同样适用于字段验证器。项目验证器可能有点不同,但我从未编写过项目验证器。

它也是 的一个方法,BaseValidator并返回一个类型的值Field。您可以将其直接分配给您想要的目标字段的类型,例如HtmlField(Sitecore 已经实现了转换运算符,因此您可以这样做):

HtmlField htmlField = field;
于 2016-05-24T08:20:45.587 回答
0

我设法为此创建了一个解决方法,它似乎对我有用。我不高兴我不知道为什么controlToValidate从来没有价值,但我的解决方法设法获得尚未保存的新价值。

基本上,我已经覆盖了运行的代码GetItem(),并且我在页面的 SaveArgs 中找到了新值,如下所示。魔术发生在以下行: field.Value = ((((SaveArgs) ((ClientPage) page)?.CurrentPipelineArgs)?.Items[0].Fields) ?? Array.Empty<SaveArgs.SaveField>()).FirstOrDefault(x => x.ID == field.ID)?.Value ?? field.Value;

protected override Item GetItem()
    {
        var obj = base.GetItem();
        if (obj == null || obj.Versions.Count == 0)
            return null;
        UpdateItem(obj);
        return obj;
    }

    private void UpdateItem(Item item)
    {
        Assert.ArgumentNotNull(item, nameof(item));
        using (new SecurityDisabler())
            item.Editing.BeginEdit();
        var page = (Page)null;
        var current = HttpContext.Current;
        if (current != null)
            page = current.Handler as Page;
        foreach (Field field in item.Fields)
        {
            var controlToValidate = ControlToValidate;
            if (string.IsNullOrEmpty(controlToValidate) || field.ID != FieldID)
            {
                field.Value = ((((SaveArgs) ((ClientPage) page)?
                        .CurrentPipelineArgs)?.Items[0].Fields) ?? Array.Empty<SaveArgs.SaveField>()).FirstOrDefault(x => x.ID == field.ID)
                    ?.Value ?? field.Value;
            }
            else
            {
                var str = current != null ? RuntimeValidationValues.Current[controlToValidate] : null;
                if (page != null && str != null)
                {
                    var control = page.FindControl(controlToValidate);
                    if (control != null)
                    {
                        if (control is IContentField contentField)
                            str = contentField.GetValue();
                        else if (ReflectionUtil.GetAttribute(control, typeof(ValidationPropertyAttribute)) is ValidationPropertyAttribute attribute)
                            str = ReflectionUtil.GetProperty(control, attribute.Name) as string;
                    }
                }
                if (str == null && current != null)
                    str = current.Request.Form[controlToValidate];
                if (str != null && str != "__#!$No value$!#__")
                    field.Value = str;
            }
        }
    }
于 2021-03-12T03:10:02.663 回答