使用Orchard中不同模块的部件

时间:2017-07-18 21:29:24

标签: orchardcms

我要做的是在Orchard中创建一个无法让用户注册的网站。管理员将创建用户。

我所拥有的是定义部件,记录,视图等的模块。这基本上是有效的。

现在我要做的是将UserPart(来自Orchard.Users)添加到我模块中的一个部分。

我不知道该怎么做。我需要为UserPart显示的字段以及同一视图中父部件的字段。这也需要以保存发生时所有UserPart字段发送到Orchard.Users模块的方式完成。

有关如何操作的任何建议,指示或链接?

谢谢!

... UPDATE

激活过滤器是一个有趣的想法。我最初选择了迁移路线。现在,我会试着让这个方法起作用。

为简单起见,假设我有一个“公司”类型(实际类型还有更多),它有一个“CompanyName”和一个UserPart。

以下是不同的部分......

Migrations.cs(简化)

public int Create()
{
SchemaBuilder.CreateTable("CompanyPartRecord", table =>  table.ContentPartRecord()
.Column("CompanyName", DbType.AnsiString, c => c.WithLength(50))
.Column("UserId", DbType.Int32));

SchemaBuilder.CreateForeignKey("FK_CompanyPartRecord_UserPartRecord", "CompanyPartRecord", new[] {"UserId" }, "Orchard.Users", "UserPartRecord", new[] { "Id" })

ContentDefinitionManager.AlterTypeDefinition("Company", type => type.WithPart("CommonPart").WithPart("UserPart"));
}

CompanyPartRecord

public class CompanyPartRecord : ContentPartRecord
{
    public virtual string CompanyName { get; set; }
    public virtual int? UserId { get; set; }
}                                    

CompanyPart

public class CompanyPart : ContentPart<CompanyPartRecord>
{
    internal LazyField<UserPart> UserPartField = new LazyField<UserPart>();

    public string CompanyName
    {
        get { return Record.CompanyName; }
        set { Record.CompanyName = value; }
    }

    public UserPart User
    {
        get { return UserPartField.Value;}
        set { UserPartField.Value = value; }
    }
}   

处理程序

public class CompanyPartHandler : ContentHandler
{
    private readonly IContentManager _manager;

    public CompanyPartHandler(IRepository<CompanyPartRecord> repository, IContentManager manager)
    {
        _manager = manager;
        Filters.Add(StorageFilter.For(repository));            
        OnActivated<CompanyPart>(OnActivatedHandler);
    }

    private void OnActivatedHandler(ActivatedContentContext context, CompanyPart part)
    {
        if(part.User == null)
        {
            part.User = _manager.Create<UserPart>("User");
        }
        else
        {
            part.User = _manager.Get<UserPart>(part.User.Id);
        }
    }        
}

驱动程序

public class CompanyPartDriver : ContentPartDriver<CompanyPart>
{
    protected override DriverResult Editor(CompanyPart part, dynamic shapeHelper)
    {
        return ContentShape("Parts_Company_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts/Company", 
                                                                                    Model: part, Prefix: Prefix));
    }

    protected override DriverResult Editor(CompanyPart part, IUpdateModel updater, dynamic shapeHelper)
    {
        updater.TryUpdateModel(part, Prefix, null, null);
        return Editor(part, shapeHelper);
    }
}

控制器

public class AdminCompanyController : Controller, IUpdateModel
{
    private readonly IOrchardServices _services;
    private readonly INotifier _notifier;
    private readonly IContentManager _contentManager;
    private readonly ITransactionManager _transactionManager;
    private readonly Localizer T = NullLocalizer.Instance;

    public AdminCompanyController(IOrchardServices services)
    {
        _services = services;
        _notifier = services.Notifier;
        _contentManager = services.ContentManager;
        _transactionManager = services.TransactionManager;
    }

    public ActionResult Create()
    {
        var company = _contentManager.New<CompanyPart>("Company");
        var model = _contentManager.BuildEditor(company);
        return View(model);
    }

    [HttpPost, ActionName("Create")]
    public ActionResult CreatePOST()
    {
        var contentItem = _contentManager.New<CompanyPart>("Company");
        var model = _contentManager.UpdateEditor(contentItem, this);

        if (!ModelState.IsValid)
        {
            _transactionManager.Cancel();
            return View(model);
        }

        _contentManager.Create(contentItem.ContentItem);
        _notifier.Information(T("Company has been saved"));

        return RedirectToAction("Index");            
    }


    public ActionResult Edit(int Id)
    {
        var contentItem = _services.ContentManager.Get(Id);
        dynamic model = _services.ContentManager.BuildEditor(contentItem);
        return View(model);
    }

    [HttpPost, ActionName("Edit")]
    public ActionResult EditPOST(int Id)
    {
        var contentItem = _contentManager.Get<CompanyPart>(Id);
        var model = _contentManager.UpdateEditor(contentItem, this);
        _notifier.Information(T("Company has been saved"));

        return RedirectToAction("Index");
    }

    public ActionResult Delete(int Id)
    {
        var contentItem = _contentManager.Get<CompanyPart>(Id);
        _contentManager.Destroy(contentItem.ContentItem);
        return RedirectToAction("Index");
    }

    bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
    {
        return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
    }

    public void AddModelError(string key, LocalizedString errorMessage)
    {
        ModelState.AddModelError(key, errorMessage.ToString());
    }
}

查看(创建)

@{ Layout.Title = T("Add Company").ToString(); }

@using (Html.BeginFormAntiForgeryPost()) 
{    
@Display(Model)
}

编辑模板

@model SDS.Models.CompanyPart

<fieldset>
    @Html.LabelFor(m => m.CompanyName)
    @Html.TextBoxFor(m => m.CompanyName)
</fieldset>

@*

What goes here to display UserPart?

*@

所以这就是我在的地方。我可以看到ContentItem(CompanyType)。我可以输入名称并保存。该名称将保存到数据库。现在,UserPart已保存到数据库,但所有字段都是空白的。

我坚持的部分是在编辑器模板中放置什么来显示UserPart字段,以便值到达UserPart驱动程序并最终到达db。

关于如何做到这一点的任何想法?

谢谢!

1 个答案:

答案 0 :(得分:0)

因此,您不会将零件附加到零件上,而是将零件附加到内容项目,您可以通过多种方式执行此操作。

您可以通过管理界面执行此操作,但这不是代码驱动的解决方案,如果您有多个环境或需要重新部署新版本的代码,则会出现问题。

您可以在迁移中创建新内容项时附加部件。这可能是一个很好的解决方案,如果您已经运行了迁移,则可以通过更新迁移来执行此操作。这允许通过管理屏幕管理部件,但有缺点,因为它可以被删除,如果你有依赖于部件的代码,那么你将开始出错。

最后一种方法是使用Activating Filter.

动态附加零件
  

ActivatingFilter类 - 从代码中将部件附加到内容类型。与通过迁移附加零件相反,使用此过滤器附加的零件既不会显示在仪表板中,也不会将用户从类型中删除。这是附加应该始终存在于给定内容类型的部分的合法方式。

所以这样做: 1.将Orchard.Users的引用添加到自定义项目中。 2.为你创建一个处理程序。比如MyPartHandler 3.然后像这样添加激活处理程序

Filters.Add(ActivatingFilter.For<UserPart>("MyContentType"));

因此,现在您的代码中的任何位置都可以访问UserPart(如果您已经拥有自己的部分,或使用

内容项)
var userPart = myPart.As<UserPart>();