0
votes

I'm creating a custom part that will save an IEnumerable list of dates using knockout for the admin UI.

Everything is working ok except I'm not sure how to get the posted json data, to push into the database...

Model

namespace HappyCity.Parts.Models {

    [OrchardFeature("HappyCity.Parts.ImportantDates")]
    public class ImportantDateListRecord : ContentPartRecord {
        public virtual string Title { get; set; }
    }

    [OrchardFeature("HappyCity.Parts.ImportantDates")]
    public class ImportantDateListPart : ContentPart<ImportantDateListRecord> {

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

        public string JsonDates { get; set; }


        private readonly LazyField<IEnumerable<ImportantDateRecord>> _importantDates = new LazyField<IEnumerable<ImportantDateRecord>>();
        public LazyField<IEnumerable<ImportantDateRecord>> ImportantDatesField { get { return _importantDates; } }
        public IEnumerable<ImportantDateRecord> ImportantDates
        {
            get { return _importantDates.Value; }
        }

    }

    [OrchardFeature("HappyCity.Parts.ImportantDates")]
    public class ImportantDateRecord 
    {
        [JsonProperty("id")]
        public virtual int Id { get; set; }

        [JsonProperty("title")]
        public virtual string Title { get; set; }

        [JsonProperty("date")]
        public virtual DateTime? Date { get; set; }

        [JsonProperty("description")]
        public virtual string Descripiton { get; set; }
        //public virtual string Link { get; set; }
    }

}

Migration

 public class Migrations : DataMigrationImpl {

        public int Create() {
            // Creating table ImportantDatesRecord
            SchemaBuilder.CreateTable(typeof(ImportantDateListRecord).Name, table => table
                .ContentPartRecord()
                .Column<string>("Title")
            );

            // make the date list part attachable
            ContentDefinitionManager.AlterPartDefinition(typeof(ImportantDateListPart).Name,
                builder => builder.Attachable());


            // Creating table ImportantDateRecord
            SchemaBuilder.CreateTable("ImportantDateRecord", table => table
                .Column("Id", DbType.Int32, c => c.Identity())
                .Column("Title", DbType.String)
                .Column("Date", DbType.DateTime)
                .Column("Descripiton", DbType.String)
            );


            return 1;
        }


    }

Driver

namespace HappyCity.Parts.Drivers {

    [OrchardFeature("HappyCity.Parts.ImportantDates")]
    public class ImportantDatesDriver: ContentPartDriver<ImportantDateListPart> {

        // This prefix will be used to distinguish between similarly named input fields when building the editor form
        protected override string Prefix
        {
            get { return "HappyCity.Parts.ImportantDates.ImportantDateListPart"; }
        }

        // This method gets called when building the display shape of the content item the part is attached to.
        protected override DriverResult Display(ImportantDateListPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_ImportantDates",
                () => shapeHelper.Parts_ImportantDates(DisplayType: displayType));
        }

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

            return ContentShape("Parts_ImportantDates_Edit",
                () => shapeHelper.EditorTemplate(
                    TemplateName: "Parts/ImportantDates",
                    Model: part,
                    Prefix: Prefix));
        }

        //POST
        protected override DriverResult Editor(
            ImportantDateListPart part, IUpdateModel updater, dynamic shapeHelper) {

            updater.TryUpdateModel(part, Prefix, null, null);

            return Editor(part, shapeHelper);
        }

    }


}

Handler

public ImportantDatesHandler(IRepository<ImportantDateListRecord> repository , Work<IImportantDatesManager> importantDatesManager)
        {
            Filters.Add(StorageFilter.For(repository));

            OnActivated<ImportantDateListPart>((context, part) =>
            {
                part.ImportantDatesField.Loader(() => importantDatesManager.Value.GetDates());
            });


            OnUpdating<ImportantDateListPart>((context, part) =>
            {

                var JsonDates = part.JsonDates;
                // ***** this just gives me the current dates from the db not the ones poseted in the form. 


                // ***** if i create a list of dates like this they will be saved to the database
                //var dates = new List<ImportantDateRecord>();
                //dates.Add(new ImportantDateRecord
                //{
                //    Title = "test date",
                //    Date = new DateTime(1977, 8, 15),
                //    Descripiton = "lorem ipsum blur"
                //});


                //foreach (var importantDateRecord in JsonDates)
                //{
                //    importantDatesManager.Value.SaveDate(importantDateRecord);
                //}

            });

        }

Service

 public interface IImportantDatesManager : IDependency
    {
        IEnumerable<ImportantDateRecord> GetDates();
        IEnumerable<ImportantDateRecord> GetDates(int maxCount);
        void SaveDate(ImportantDateRecord importantDate);

    }

    [OrchardFeature("HappyCity.Parts.ImportantDates")]
    public class ImportantDatesManager : IImportantDatesManager {

        private readonly IRepository<ImportantDateRecord> _importantDatesRepostiory;


        public ImportantDatesManager(IRepository<ImportantDateRecord> importantDatesRepostiory) {
            _importantDatesRepostiory = importantDatesRepostiory;
        }


        public IEnumerable<ImportantDateRecord> GetDates() {
            return _importantDatesRepostiory.Table.AsEnumerable();
        }

        public IEnumerable<ImportantDateRecord> GetDates(int maxCount) {
            return _importantDatesRepostiory.Table.Take(maxCount);
        }

        public void SaveDate(ImportantDateRecord importantDate) {
            // Let's also practice exception handling.
            if (String.IsNullOrEmpty(importantDate.Title)) throw new ArgumentNullException("importantDate", "Title was null");

            var date = _importantDatesRepostiory.Fetch(record => record.Id == importantDate.Id).FirstOrDefault();

            if (date == null)
            {
                date = new ImportantDateRecord();
                _importantDatesRepostiory.Create(date);
            }

            date.Title = importantDate.Title;
            date.Date = importantDate.Date;
            date.Descripiton = importantDate.Descripiton;
        }
    }

Somewhere in the handler I should be able to get the new values posted in the request. but How ?

Also in the SaveDate Method on the server don't I need _importantDatesRepostiroy.update ?

1

1 Answers

0
votes

You want to use the OnUpdated handler, rather than the OnUpdating handler.

OnUpdating happens before each Content Part Driver's Editor() method (POST) is called, and OnUpdated happens afterwards. The Content Part Driver's Editor() method is where you are performing your IUpdater.TryUpdateModel() call, which you are using to populate the content part with data from the form.

By waiting for the OnUpdated handler, the part now contains the JsonDates string value that you have posted from your view.

With regard to your question about whether it is necessary to call IRepository.Update(), you do not need it in most cases, since there is an implicit transaction around the entire request and your changes will be saved to the database at the end of the request.