我要做的是在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。
关于如何做到这一点的任何想法?
谢谢!
答案 0 :(得分:0)
因此,您不会将零件附加到零件上,而是将零件附加到内容项目,您可以通过多种方式执行此操作。
您可以通过管理界面执行此操作,但这不是代码驱动的解决方案,如果您有多个环境或需要重新部署新版本的代码,则会出现问题。
您可以在迁移中创建新内容项时附加部件。这可能是一个很好的解决方案,如果您已经运行了迁移,则可以通过更新迁移来执行此操作。这允许通过管理屏幕管理部件,但有缺点,因为它可以被删除,如果你有依赖于部件的代码,那么你将开始出错。
最后一种方法是使用Activating Filter.
动态附加零件ActivatingFilter类 - 从代码中将部件附加到内容类型。与通过迁移附加零件相反,使用此过滤器附加的零件既不会显示在仪表板中,也不会将用户从类型中删除。这是附加应该始终存在于给定内容类型的部分的合法方式。
所以这样做: 1.将Orchard.Users的引用添加到自定义项目中。 2.为你创建一个处理程序。比如MyPartHandler 3.然后像这样添加激活处理程序
Filters.Add(ActivatingFilter.For<UserPart>("MyContentType"));
因此,现在您的代码中的任何位置都可以访问UserPart(如果您已经拥有自己的部分,或使用
内容项)var userPart = myPart.As<UserPart>();