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 中“劫持”了我的 Contact Us 视图的路由:

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)) {}

但这会导致“值不能为空”异常。

然后我尝试将我的 Umbraco 表单声明更改为:

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

以确保将传递给视图的 ContactFormModel 发送回表面控制器。这通过了 YSOD,但在表面控制器 SendEmail 方法中,“模型”为空。

所以有几件事我不太明白:

  1. 为什么首先尝试在我的 ContactFormModel 上调用无参数构造函数?为什么视图中的 ContactFormModel 不仅仅在表面控制器方法中可用,因为这是我指定的?

  2. 当我将模型显式添加到表单帖子的路由值时,为什么它会以 null 出现?

感觉必须有一个简单的解决方案,我可能错过了一些基本的东西。搜索论坛有很多劫持路由和继承自 RenderModel 的示例,并且当自定义模型继承自 RenderModel 时,还使用自定义模型和表面控制器来处理表单帖子,但不是这两个组合。

如果我找不到解决方案,我将不得不求助于不从 RenderModel 继承,因此不允许在联系我们表单中包含任何可编辑的内容,这似乎破坏了 Umbraco 的对象。或者,创建另一个模型纯粹用于不从 RenderModel 继承但复制我的 ContactFormModel 中的所有字段的表面控制器,这简直太疯狂了!

感谢您的任何想法或建议。

4

1 回答 1

16

好的,我对这个问题没有任何回应,但现在我可以自己回答了。也许这是一个根本性的疏忽,但不是那么明显,而且 Umbraco 论坛等关于从 RenderModel 继承的信息相当有限。

本质上,正如我的第一直觉一样,答案是通过提供无参数构造函数来解决原始异常“没有为此对象定义无参数构造函数”。困难在于为我的模型确定在无参数构造函数中放入什么,因为它继承自 Umbraco RenderModel,它需要将 IPublishedContent 实例传递给它的构造函数。

幸运的是,在浏览 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 回答