我在CMS内容树中有一个文档类型,模板和一个页面,用于联系页面。文档类型没有CMS数据属性,因为它不需要任何属性。我将Models Builder用于其他页面没有问题,但是对于这个页面,我在我的MVC项目中创建了自己的自定义模型。
我已经阅读了我能找到的每个教程,并查看了每个论坛帖子并在Umbraco论坛和Stackoverflow上发布,对于我的生活,我无法弄清楚我做错了什么。模型名称和命名空间与自动生成的模型构建器1不冲突。
我的理解是发布表单,SurfaceController是要走的路 - RenderController更适合呈现内容。所以我的控制器扩展了SurfaceController。使用Umbraco.BeginUmbracoForm(等)
我已经尝试了SurfaceController和RenderController的每个组合与UmbracoTemplatePage,UmbracoViewPage以及改变我的模型的每种方式,以扩展RenderModel和IPublishedContent来测试每个。在尝试使用RenderController时,我已使用RenderModel参数覆盖默认的Index方法,以使用renderModel参数创建模型的实例。
通常我得到的错误是“无法将源类型Umbraco.Web.Models.RenderModel绑定到模型类型xxx”。有时我尝试过的组合允许Get成功,然后在Post上给出这个错误。
我甚至尝试从CMS中删除页面并使用标准的MVC控制器和路由 - 这允许我显示页面,甚至在我的视图上使用标准的Html.BeginForm,我在尝试时出错发布表单(尽管控制器中的代码中有一个断点),它也声明它“无法将源类型Umbraco.Web.Models.RenderModel绑定到模型类型xxx”
这不是那么困难。我准备在这个阶段将笔记本电脑扔出窗外。
我做错了什么????或者至少没有看到我的代码,任何人都可以告诉我这是假设的要做什么?如何将自定义模型表单发布到Umbraco 7.5控制器,而不需要CMS发布的内容属性?
目前,我的视图看起来像这样:
@inherits UmbracoViewPage<Models.Contact>
...
using (Html.BeginUmbracoForm<ContactController>("Contact", FormMethod.Post
我的控制器看起来像这样:
public class ContactController : SurfaceController
{
public ActionResult Contact()
{
return View("~/Views/Contact.cshtml");
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(Contact contactForm)
{
...
}
我的模型看起来像这样:
public class Contact : RenderModel
{
public Contact() : base(UmbracoContext.Current.PublishedContentRequest.PublishedContent, UmbracoContext.Current.PublishedContentRequest.Culture)
{
}
public Contact(IPublishedContent content) : base(content, CultureInfo.CurrentUICulture)
{
}
[Display(Name = "First Name", Prompt = "First Name")]
public string FirstName { get; set; }
...
更新:如果我将模型用于模型构建器自动创建的CMS页面,则Get和Post工作正常。但是,当我自定义模型时(即我在〜/ App_Data / Models中放置了同名的部分类并在Developer选项卡上重新生成模型),我发布的模型中的自定义属性始终为null。
我可以从请求表单变量中手动填充这些变量,但这似乎是错误和混乱的。这是怎么回事?
public class ContactPageController : SurfaceController
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(ContactPage contactForm)
{
try
{
contactForm.FirstName = Request.Form["FirstName"];
contactForm.LastName = Request.Form["LastName"];
contactForm.EmailAddress = Request.Form["EmailAddress"];
contactForm.Telephone = Request.Form["Telephone"];
contactForm.Message = Request.Form["Message"];
var captchaIsValid = ReCaptcha.Validate(ConfigurationManager.AppSettings["ReCaptcha:SecretKey"]);
if (ModelState.IsValid && captchaIsValid)
{
// Do what you need
TempData["EmailSent"] = true;
return RedirectToCurrentUmbracoPage();
}
if (!captchaIsValid)
{
ModelState.AddModelError("ReCaptchaError", "Captcha validation failed - Please try again.");
}
return RedirectToCurrentUmbracoPage();
}
catch (Exception ex)
{
LogHelper.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, null, ex);
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
}
更多信息:罗伯特第一次接近,谢谢你。我尝试过使用PartialViews和ChildActions的一种方法,但显然我没有正确地做到这一点。我是否正确地说这个方法需要的原因(即为什么你不能将自定义属性添加到主视图所绑定的模型中)是因为我使用的是模型生成器?
因此,我收到的奇怪错误之一是两个想要代表联系页面的类,另一个关于它期望字典中的一种类型(ContactPage)但接收另一个(联系人) - 即使我已经做了在视图或控制器中没有引用ContactPage。这对我来说,ModelsBuilder在幕后的app启动时为模型添加了文档类型的映射?这也许是为什么你最好采用这种方法让ModelsBuilder做它的事情,并以这种方式用局部视图构建你自己的模型?
我发现这个主题的文档质量确实很差。不确定好的东西是否闭门造车,即需要付费的Umbraco会员资格?对于一个所谓的开源系统,对我来说感觉有点阴暗。
当你知道怎么做时很容易!!
答案 0 :(得分:4)
根据您的情况,SurfaceController
是您猜测的最有可能的候选人,但请将该控制器中的操作视为应用于部分视图,而不是页面使用的完整视图。
不要尝试使用ModelsBuilder ContactPage
模型,而是创建自己的模型(原始的Contact
模型) - 将其视为数据传输对象,如果你这样做的话需要以任何理由将任何属性应用回ContactPage
模型。
我发现SurfaceController
在以下条件下获得了最大的成功:
Umbraco.Web.Mvc.UmbracoViewPage<Contact>
。BeginUmbracoForm<ContactController>
,将POST操作指定为其中一个参数(取决于您使用的是哪个签名)您不需要使用Request.Form
这样填充任何模型属性。
例如,我的一个项目中的代码如下所示:
public class FormsController : SurfaceController
{
[ChildActionOnly]
public ActionResult ContactUs()
{
return PartialView(new ContactForm ());
}
[HttpPost]
public async Task<ActionResult> HandleContactUs(ContactForm model)
{
if (ModelState.IsValid)
{
if (!await model.SendMail(Umbraco)) // Do something with the model.
{
}
}
return RedirectToCurrentUmbracoPage(); // Send us back to the page our partial view is on
}
}
@inherits Umbraco.Web.Mvc.UmbracoViewPage<ContactForm>
@using Digitalsmith.ReCaptcha
@using (Html.BeginUmbracoForm<FormsController>("HandleContactUs"))
{
...
}
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ContactPage>
@{
Layout = "_Layout.cshtml";
}
@Html.Action("ContactUs", "Forms")