Orchard ComputedField无法正常工作

时间:2014-09-30 15:39:46

标签: c# asp.net-mvc orchardcms

我有一个包含Password字段的部分,我希望在数据库中对其进行加密。我使用Orchard.Email作为灵感来做到这一点,但我使用ComputedField遇到了问题。

编辑部件时,ComputedField应该负责加密。我编写了一个处理程序,它应该为Getter设置SetterComputedField委托,但是当到达驱动程序更新模型时,这些委托是NULL,所以我得到一个NullReferenceException。但是,当我检索部件时,代理设置正确。

我的代码:

部分

public class TaskServerPart : ContentPart<TaskServerPartRecord>
{
    private readonly ComputedField<string> _password = new ComputedField<string>();

    public ComputedField<string> PasswordField
    {
        get { return _password; }
    }

    public string Name
    {
        get { return Record.Name; }
        set { Record.Name = value; }
    }
    public string Domain
    {
        get { return Record.Domain; }
        set { Record.Domain = value; }
    }
    public string Username
    {
        get { return Record.Username; }
        set { Record.Username = value; }
    }

    public string Password
    {
        get { return _password.Value; }
        set { _password.Value = value; }
    }
} 

PartRecord

public class TaskServerPartRecord : ContentPartRecord
{
    public virtual string Name { get; set; }
    public virtual string Domain { get; set; }
    public virtual string Username { get; set; }
    public virtual string Password { get; set; }
}

处理程序

public class TaskServerPartHandler : ContentHandler
{
    private readonly IEncryptionService _encryptionService;

    public TaskServerPartHandler(IRepository<TaskServerPartRecord> repository, IEncryptionService encryptionService)
    {
        _encryptionService = encryptionService;
        Logger = NullLogger.Instance;
        Filters.Add(new ActivatingFilter<TaskServerPart>("Site"));
        Filters.Add(StorageFilter.For(repository));
        OnLoaded<TaskServerPart>(LoadHandlers);
    }
    void LoadHandlers(LoadContentContext context, TaskServerPart part)
    {
        part.PasswordField.Getter(() =>
        {
            try
            {
                return String.IsNullOrWhiteSpace(part.Record.Password) ? String.Empty : Encoding.UTF8.GetString(_encryptionService.Decode(Convert.FromBase64String(part.Record.Password)));
            }
            catch
            {
                Logger.Error("The task server password could not be decrypted. It might be corrupted, try to reset it.");
                return null;
            }
        });

        part.PasswordField.Setter(value => part.Record.Password = String.IsNullOrWhiteSpace(value) ? String.Empty : Convert.ToBase64String(_encryptionService.Encode(Encoding.UTF8.GetBytes(value))));
    }
}

驱动程序

public class TaskServerDriver : ContentPartDriver<TaskServerPart>
{
    protected override string Prefix { get { return "TaskServer"; } }

    //GET
    protected override DriverResult Editor(
        TaskServerPart part, dynamic shapeHelper)
    {

        return ContentShape("Parts_TaskServer_Edit",
                            () => shapeHelper.EditorTemplate(
                                TemplateName: "Parts/TaskServer",
                                Model: part,
                                Prefix: Prefix))
            ;
    }
    //POST
    protected override DriverResult Editor(
        TaskServerPart part, IUpdateModel updater, dynamic shapeHelper) {
        return ContentShape("Parts_TaskServer_Edit", () => {
            var previousPassword = part.Password; // This fails, because the ComputedField has no Getter or Setter delegates
            updater.TryUpdateModel(part, Prefix, null, null);

            // restore password if the input is empty, meaning it has not been changed
            if (String.IsNullOrEmpty(part.Password)) {
                part.Password = previousPassword;
            }
            return shapeHelper.EditorTemplate(TemplateName: "Parts/TaskServer", Model: part, Prefix: Prefix);
        });
    }
}

更新

我在处理程序上设置了一个断点,以查看它何时被调用。

  1. 第一次调用它时,属性具有数据库中记录的值,这是有意义的。我修改了其中一个属性,看看会发生什么并跟踪对象。 (编辑:我已经在Watch窗口找到&#34; Make Object ID&#34;选项,它告诉我同样的事情。)
  2. 此时,驱动程序将调用具有我在步骤1中设置的属性值的项目,但ComputedField的Getter和Setter为NULL,因此发生异常并且更新失败
  3. 在此之后,Handler再次调用我的另一个实例,我假设在数据库应该更新之后重定向。
  4. 我为我的部分添加了额外的属性(但不是部分记录)。如果我在断点到达处理程序时设置了这个属性的值,那么当我到达驱动程序时,该值就不存在了,所以我处理的是与我设置ComputedField&#39的部分对象不同的部分对象。 ; s委托,虽然底层记录对象是相同的。使用&#34;创建对象ID&#34;,我发现基本相同的事情:我正在处理三个TaskServerPart实例。第二个实例是我的驱动程序要处理的实例,它是处理程序未执行的唯一实例。

    对于最终在驱动程序中的对象,InitializedActivated事件,如果我使用其中一个而不是{{1}事件?

1 个答案:

答案 0 :(得分:0)

未针对发送给驱动程序的对象触发Loaded事件。 Initialized事件发生了,因此我使用该事件来设置Getter的{​​{1}}和Setter代表。