10

シナリオ:

私は MVC を使用して Umbraco 6 でサイトを構築しています - 私は Umbraco にかなり慣れていませんが、チュートリアルなどに従ってこれまですべてを行ってきました。ほとんどの場合、すべてがうまく機能します。

したがって、次のコードでレンダリングされた部分ビューとして作成された「お問い合わせ」フォームがあります。

@using (Html.BeginUmbracoForm("SendEmail", "ContactFormSurface"))
{

これは私の ContactFormSurfaceController にポストバックします:

public class ContactFormSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
    [HttpPost]
    public ActionResult SendEmail(ContactFormModel model)
    {

これで、私の ContactFormModel は Umbraco RenderModel から継承され、別の ContactFormController でお問い合わせビューのルートを「ハイジャック」しています。

public class ContactFormController : RenderMvcController
{
    //
    // GET: /Contact-us/

    public override ActionResult Index(RenderModel model)
    {
        var contactFormModel = new ContactFormModel(model);
        return CurrentTemplate(contactFormModel);
    }

Umbraco のコンテンツに基づいて、連絡先フォーム内で柔軟なヘッダーと送信ボタン テキストを使用できるようにするために、これが必要です。私の ContactFormModel は、そのコンストラクターで RenderModel を受け取り、基になる Umbraco コンテンツにアクセスできるようにします。

public class ContactFormModel : RenderModel
{
    #region Ctr

    public ContactFormModel(RenderModel model) : base(model.Content, model.CurrentCulture) {}

    #endregion


    #region Contact Form Fields

    [Display(Name = "Your Name")]
    [Required]
    public string Name { get; set; }

問題:

フォームがサーフェス コントローラーの SendEmail メソッドにポストバックされると、新しい ContactFormModel をインスタンス化しようとしているように見え、次の例外で YSOD が発生します。

このオブジェクトにはパラメーターなしのコンストラクターが定義されていません。

私が最初に考えたのは、SendEmail サーフェス コントローラー メソッド内の Umbraco コンテンツに実際にアクセスする必要がないため、パラメーターなしのコンストラクターを提供するということでした。最初にビューをレンダリングするときだけアクセスしたいのです。しかし、これはそれほど簡単ではありません。基本の RenderModel では、そのコンストラクターに IPublishedContent オブジェクトを渡す必要があるからです。私はnullを渡してみました、そしてまた:

public ContactFormModel() :base(new DynamicPublishedContent(null)) {}

しかし、その結果、「値を null にすることはできません」という例外が発生します。

次に、Umbraco フォーム宣言を次のように変更してみました。

@using (Html.BeginUmbracoForm("SendEmail", "ContactFormSurface", new {model = @Model}))

ビューに渡される ContactFormModel がサーフェス コントローラーに送り返されるようにします。これは YSOD を通過しますが、サーフェス コントローラーの SendEmail メソッド内では、"モデル" は null です。

だから、私が本当に理解していないことがいくつかあります:

  1. そもそも ContactFormModel でパラメーターなしのコンストラクターを呼び出そうとするのはなぜですか? ビューからの ContactFormModel がサーフェス コントローラー メソッドで利用できないのはなぜですか?

  2. フォーム ポストのルート値にモデルを明示的に追加すると、null になるのはなぜですか?

これには簡単な解決策が必要なように感じますが、根本的な何かが欠けている可能性があります。フォーラムを検索すると、ルートをハイジャックして RenderModel から継承する例がたくさんあります。また、カスタム モデルとサーフェス コントローラーを使用してフォーム ポストを処理する例もありますが、カスタム モデルが RenderModel から継承する場合、2 つのことを組み合わせたものではありません。

これに対する解決策が見つからない場合は、RenderModel から継承せず、お問い合わせフォーム内で編集可能なコンテンツを許可しないようにする必要があります。これは、Umbraco の目的を無効にしているようです。または、RenderModel から継承せず、ContactFormModel のすべてのフィールドを複製するサーフェス コントローラーで使用するためだけに別のモデルを作成します。

アイデアやアドバイスをありがとう。

4

1 に答える 1

16

わかりました、この質問に対する回答はありませんでしたが、今は自分で答える立場にあります。根本的な見落としだったのかもしれませんが、明らかな私見ではなく、RenderModel からの継承に関する Umbraco フォーラムなどの情報はかなり限られています。

基本的に、私の最初の本能のように、パラメーターなしのコンストラクターを提供することにより、元の例外「このオブジェクトに対してパラメーターなしのコンストラクターが定義されていません」を解決することが答えです。コンストラクターに渡される IPublishedContent インスタンスを必要とする Umbraco RenderModel から継承するため、モデルのパラメーターなしのコンストラクター内に何を配置するかが問題になります

幸いなことに、Umbraco フォーラムでブラウズしているときに、この投稿を見つけました: http://our.umbraco.org/forum/developers/api-questions/40754-Getting-CurrentPage-from-SurfaceController

私が完全には理解していなかったのは、現在のページ/ビュー情報が Umbraco Context を介してどのように渡されるかということです。上記の投稿に従って、カスタム モデル用にいくつかの新しいコンストラクターを作成しました。

    public ContactFormModel() : this(new UmbracoHelper(UmbracoContext.Current).TypedContent(UmbracoContext.Current.PageId)) {}
    public ContactFormModel(IPublishedContent content) : base(content) {}

これらを配置して、フォームを Surface Controller メソッドに戻すと、まるで魔法のように、ContactFormModel に入力されたすべての詳細が取り込まれます。

于 2013-07-09T15:09:13.833 に答える