2

I want to programmatically create a content type which includes, among other things, an image. The obvious way to do this seems to be to use a MediaLibraryPickerField.

My question is very similar to this one, but unfortunately it doesn't give an answer

My problem is I can't get the field to show up. I've been digging through the docs and other online recourses, but no luck so far. I'm going to post all my code here in the hopes that someone can see what I'm missing. I'm learning, so if I'm doing anything weird, please don't hesitate to point it out.

My content type should consist of:

  • Title
  • Body
  • Description
  • Image

Migration.cs:

SchemaBuilder.CreateTable("MyTypePartRecord",
    table => table
        .ContentPartRecord()
        .Column<string>("Description", c => c.Unlimited())
    );

ContentDefinitionManager.AlterPartDefinition(
    "MyTypePart", builder => builder
        .WithDescription("Turns content types into a MyType.")
        .WithField("Image", f => f.OfType(typeof(MediaLibraryPickerField).ToString()))
        .Attachable()
        );

ContentDefinitionManager.AlterTypeDefinition(
    "MyType",cfg => cfg
        .WithPart("CommonPart")
        .WithPart("MyTypePart")
        .WithPart("TitlePart")
        .WithPart("BodyPart")
        .Creatable()
    );

Models/MyTypePart.cs:

public class MyTypePart : ContentPart<MyTypePartRecord>
{
    public string Description
    {
        get { return Record.Description; }
        set { Record.Description = value; }
    }
}

Models/MyTypePartRecord.cs:

public class MyTypePartRecord : ContentPartRecord
{
    [StringLengthMax]
    public virtual string Description { get; set; }
}

Models/MyTypePartRecordHandler.cs:

public class MyTypePartRecordHandler : ContentHandler
{
    public MyTypePartRecordHandler(IRepository<MyTypePartRecord> repository) {
        Filters.Add(StorageFilter.For(repository));
    }
}

Drivers/MyTypeDriver.cs

public class MyTypeDriver : ContentPartDriver<MyTypePart> {

    public MyTypeDriver() {

    }

    // GET
    protected override DriverResult Display(MyTypePart part, string displayType, dynamic shapeHelper) {
        return ContentShape("Parts_MyType",
            ()=> shapeHelper.Parts_MyType(
                Description: part.Description
                ));
    }

    // GET
    protected override DriverResult Editor(MyTypePart part, dynamic shapeHelper)
    {
        return ContentShape("Parts_MyType_Edit",
            () => shapeHelper.EditorTemplate(
                TemplateName: "Parts/MyType",
                Model: part,
                Prefix: Prefix));
    }

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

}

Views/EditorTemplates/Parts/MyType.cshtml:

@model MySolution.Models.MyType

<fieldset>
    <div class="editor-label">@T("Description"):</div>
    <div class="editor-field">
        @Html.TextBoxFor(m => m.Description)
        @Html.ValidationMessageFor(m => m.Description)
    </div>
</fieldset>

Views/Parts/MyType.cshtml:

@using MySolution.Models

<div>Description: @Model.Description</div>

placement.info:

<Placement>
  <Place Parts_MyType="Content:1"/>
  <Place Parts_MyType_Edit="Content:7.5"/>
</Placement>

UPDATE

As suggested, I changed MyTypePart to MyType throughout the module. Now, in Content Definition, I see the Image Field directly in my content type, instead of it being a field of the MyTypePart part of the content type. I still don't see the field when creating a new item, though.

Community
  • 1
  • 1
Rik
  • 28,507
  • 14
  • 48
  • 67
  • When you go to content definitions, does your field appear? I think the problem is that you added your field to your part instead of adding it to a part that has the same name as the type. – Bertrand Le Roy Feb 06 '14 at 17:14
  • 1
    When I inspect the Content type or the part in Content Definition, I can see the field, but when i try to create a new item, only the Title, Body and Description fields show up. So it seems to me the Content Type and Part are created correctly, but I'm doing something else wrong. – Rik Feb 07 '14 at 08:25
  • Changing the part's name to match the type, or adding the field to another part with the same name as the type did not solve the problem. – Rik Feb 07 '14 at 08:32
  • Please show the modified migration. Also, make sure you reset your database, otherwise the new migration won't run. – Bertrand Le Roy Feb 07 '14 at 17:45
  • @BertrandLeRoy I added an update to the question. – Rik Feb 10 '14 at 12:16

1 Answers1

2

I finally found out what was wrong. Instead of this:

.WithField("Image", f => f.OfType(typeof(MediaLibraryPickerField).ToString()))

I should have done this:

.WithField("Image", f => f.OfType("MediaLibraryPickerField"))

The former would result in a field of type Orchard.MediaLibrary.Fields.MediaLibraryPickerField instead of just MediaLibraryPickerField and apparently Orchard didn't know how to handle it.

Rik
  • 28,507
  • 14
  • 48
  • 67
  • I make a similar mistake by using the wrong setting name. I.e. I used `DateTimeFieldSettings.Display` where I needed to use `DateTimeFieldSettings.DateTimeFieldDisplays`. – Shaun Luttin Jul 31 '14 at 00:48
  • You can use `.Name` instead of `.ToString()` – devqon Jul 07 '15 at 13:21