orchardcms - Orchard Custom Settings Not Persisting -
i'm pulling hair out on one; should simple yet can't figure out issue.
i'm trying save custom settings in module. used orchard.email module example on how plug 'settings' menu; code follows:
migrations.cs
public class customsettingsmigrations : datamigrationimpl { public int create() { schemabuilder.createtable("customsettingspartrecord", table => table .contentpartrecord() .column<string>("gatewayurl") .column<string>("merchantid") .column<string>("merchantpassword") .column<bool>("sandboxmode") .column<string>("sandboxgatewayurl") .column<string>("sandboxmerchantid") .column<string>("sandboxmerchantpassword") ); return 1; } } models/customsettingspartrecord.cs
public class customsettingspartrecord : contentpartrecord { public virtual string gatewayurl { get; set; } public virtual string merchantid { get; set; } public virtual string merchantpassword { get; set; } public virtual bool sandboxmode { get; set; } public virtual string sandboxgatewayurl { get; set; } public virtual string sandboxmerchantid { get; set; } public virtual string sandboxmerchantpassword { get; set; } public customsettingspartrecord() { sandboxmode = true; } } models/customsettingspart.cs
public class customsettingspart : contentpart<customsettingspartrecord> { private readonly computedfield<string> _password = new computedfield<string>(); public computedfield<string> passwordfield { { return _password; } } public string gatewayurl { { return record.gatewayurl; } set { record.gatewayurl = value; } } public string merchantid { { return record.merchantid; } set { record.merchantid = value; } } public string merchantpassword { { return record.merchantpassword; } set { record.merchantpassword = value; } } public bool sandboxmode { { return record.sandboxmode; } set { record.sandboxmode = value; } } public string sandboxgatewayurl { { return record.sandboxgatewayurl; } set { record.sandboxgatewayurl = value; } } public string sandboxmerchantid { { return record.sandboxmerchantid; } set { record.sandboxmerchantid = value; } } public string sandboxmerchantpassword { { return record.sandboxmerchantpassword; } set { record.sandboxmerchantpassword = value; } } public bool isvalid() { return ((!string.isnullorwhitespace(record.gatewayurl) && !string.isnullorwhitespace(record.merchantid)) || (record.sandboxmode && !string.isnullorwhitespace(record.sandboxgatewayurl) && !string.isnullorwhitespace(record.sandboxmerchantid))); } } handlers/customsettingsparthandler.cs
[usedimplicitly] public class customsettingsparthandler : contenthandler { private readonly iencryptionservice _encryptionservice; public customsettingsparthandler(irepository<customsettingspartrecord> repository, iencryptionservice encryptionservice) { t = nulllocalizer.instance; logger = nulllogger.instance; _encryptionservice = encryptionservice; filters.add(new activatingfilter<customsettingspart>("site")); filters.add(storagefilter.for(repository)); onloaded<customsettingspart>(lazyloadhandlers); } public localizer t { get; set; } public new ilogger logger { get; set; } void lazyloadhandlers(loadcontentcontext context, customsettingspart part) { part.passwordfield.getter(() => { try { return string.isnullorwhitespace(part.record.merchantpassword) ? string.empty : encoding.utf8.getstring(_encryptionservice.decode(convert.frombase64string(part.record.merchantpassword))); } catch (exception) { logger.error("the merchant password not decrypted. might corrupt, try reset it."); return null; } }); part.passwordfield.setter(value => part.record.merchantpassword = string.isnullorwhitespace(value) ? string.empty : convert.tobase64string(_encryptionservice.encode(encoding.utf8.getbytes(value)))); } protected override void getitemmetadata(getcontentitemmetadatacontext context) { if (context.contentitem.contenttype != "site") return; base.getitemmetadata(context); context.metadata.editorgroupinfo.add(new groupinfo(t("custom"))); } } drivers/customsettingspartdriver.cs
public class customsettingspartdriver : contentpartdriver<customsettingspart> { private const string templatename = "parts/customsettings"; public customsettingspartdriver() { t = nulllocalizer.instance; } public localizer t { get; set; } protected override string prefix { { return "customsettings"; } } protected override driverresult editor(customsettingspart part, dynamic shapehelper) { return contentshape("parts_customsettings_edit", () => shapehelper.editortemplate(templatename: templatename, model: part, prefix: prefix)) .ongroup("custom"); } protected override driverresult editor(customsettingspart part, iupdatemodel updater, dynamic shapehelper) { return contentshape("parts_customsettings_edit", () => { var previouspassword = part.merchantpassword; updater.tryupdatemodel(part, prefix, null, null); // restore password if input empty, meaning has not been changed if (string.isnullorempty(part.merchantpassword)) { part.merchantpassword = previouspassword; } return shapehelper.editortemplate(templatename: templatename, model: part, prefix: prefix) .ongroup("custom"); }); } } views/editortemplates/parts/customsettings.cshtml
@model custommodule.models.customsettingspart @{ script.require("jquery"); } <fieldset> <legend>@t("custom settings")</legend> <div> <label for="@html.fieldidfor(m => m.gatewayurl)">@t("gateway url")</label> @html.editorfor(m => m.gatewayurl) @html.validationmessage("gatewayurl", "*") </div> <div> <label for="@html.fieldidfor(m => m.merchantid)">@t("merchant id")</label> @html.editorfor(m => m.merchantid) @html.validationmessage("merchantid", "*") </div> <div> <label for="@html.fieldidfor(m => m.merchantpassword)">@t("merchant password")</label> @html.passwordfor(m => m.merchantpassword) @html.validationmessage("merchantpassword", "*") </div> <div> @html.editorfor(m => m.sandboxmode) <label for="@html.fieldidfor(m => m.sandboxmode)" class="forcheckbox">@t("enable sandbox mode (for testing)")</label> @html.validationmessage("sandboxmode", "*") </div> <div id="sandboxsettings"> <div> <label for="@html.fieldidfor(m => m.sandboxgatewayurl)">@t("sandbox gateway url")</label> @html.editorfor(m => m.sandboxgatewayurl) @html.validationmessage("sandboxgatewayurl", "*") </div> <div> <label for="@html.fieldidfor(m => m.sandboxmerchantid)">@t("sandbox merchant id")</label> @html.editorfor(m => m.sandboxmerchantid) @html.validationmessage("sandboxmerchantid", "*") </div> <div> <label for="@html.fieldidfor(m => m.sandboxmerchantpassword)">@t("sandbox merchant password")</label> @html.editorfor(m => m.sandboxmerchantpassword) @html.validationmessage("sandboxmerchantpassword", "*") </div> </div> </fieldset> @using (script.foot()) { <script> $('#@html.fieldidfor(m => m.sandboxmode)').on('click', function() { $('#sandboxsettings').toggle($(this).prop('checked')); }); </script> } i have placement.info , can access view through "custom" menu item underneath "settings" in main menu. view loads fine, , when enter details , click 'save', form sent find , hit customsettingspartdriver.cs driverresult editor(customsettingspart part, iupdatemodel updater.. method.
i believe issue be, doesn't hit breakpoints inside return contentshape("parts_customsettings_edit, () => { lambda expression.
could shed light on how can resolve this? i'm sure it's simple issue, i've been trying figure 1 out while unsuccessfully. thanks!
okay, managed figure 1 out. feel silly asking questions answering them myself, if saves 1 person time in future, it's worth it.
the issue was, expected, in driver. appended .ongroup() extension wrong shape.
below fixed driver code:
protected override driverresult editor(customsettingspart part, iupdatemodel updater, dynamic shapehelper) { return contentshape("parts_customsettings_edit", () => { var previouspassword = part.merchantpassword; updater.tryupdatemodel(part, prefix, null, null); // restore password if input empty, meaning has not been changed if (string.isnullorempty(part.merchantpassword)) { part.merchantpassword = previouspassword; } return shapehelper.editortemplate(templatename: templatename, model: part, prefix: prefix); // offending extension -> .ongroup("custom"); }).ongroup("custom"); // in correct location } *facepalm*
Comments
Post a Comment