私はこれで髪を引っ張っています。とても単純なはずですが、問題がわかりません。
モジュールにいくつかのカスタム設定を保存しようとしています。「設定」メニューにプラグインする方法の例として、Orchard.Email モジュールを使用しました。私のコードは次のとおりです。
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;
}
}
モデル/CustomSettingsPart.cs
public class CustomSettingsPart : ContentPart<CustomSettingsPartRecord> {
private readonly ComputedField<string> _password = new ComputedField<string>();
public ComputedField<string> PasswordField {
get { return _password; }
}
public string GatewayUrl {
get { return Record.GatewayUrl; }
set { Record.GatewayUrl = value; }
}
public string MerchantId {
get { return Record.MerchantId; }
set { Record.MerchantId = value; }
}
public string MerchantPassword {
get { return Record.MerchantPassword; }
set { Record.MerchantPassword = value; }
}
public bool SandboxMode {
get { return Record.SandboxMode; }
set { Record.SandboxMode = value; }
}
public string SandboxGatewayUrl {
get { return Record.SandboxGatewayUrl; }
set { Record.SandboxGatewayUrl = value; }
}
public string SandboxMerchantId {
get { return Record.SandboxMerchantId; }
set { Record.SandboxMerchantId = value; }
}
public string SandboxMerchantPassword {
get { 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 could not be decrypted. It might be corrupt, try to 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 { get { 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 the input is empty, meaning it has not been changed
if (String.IsNullOrEmpty(part.MerchantPassword)) {
part.MerchantPassword = previousPassword;
}
return shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: part, Prefix: Prefix)
.OnGroup("custom");
});
}
}
ビュー/EditorTemplates/パーツ/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>
}
Placement.infoがあり、メイン メニューの [設定] の下にある [カスタム] メニュー項目からビューにアクセスできます。ビューが正常に読み込まれ、詳細を入力して [保存] をクリックすると、フォームが送られ、検索結果がCustomSettingsPartDriver.cs DriverResult Editor(CustomSettingsPart part, IUpdateModel updater..
メソッドにヒットします。
ラムダreturn ContentShape("Parts_CustomSettings_Edit, () => {
式内のブレークポイントにヒットしないため、これが問題の可能性がある場所だと思います。
どうすればこれを解決できるか、誰かが光を当てることができますか? 単純な問題だと思いますが、しばらくの間、これを理解しようとして失敗しました。ありがとう!