I am new to Umbraco and MVC and am having trouble implementing a Contact Us form. I did everything based on the example however it is like it cannot find the route to my ConactUsController. Any ideas where I should start to look beyond the basics? I have been stuck on this for over a day now :(
using System; using System.Collections.Generic; using System.Web; using System.ComponentModel.DataAnnotations; using System.Web.Mvc;
/// <summary> /// Summary description for ContactUsModel /// </summary> ///
namespace Lebsea.Site.Models { public class ContactUsModel { [Required] public string Name { get; set; }
[Required] [RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")] public string Email { get; set; }
[Required] public string Message { get; set; }
} }
Controller File ContactUsController.cs
using System; using System.Collections.Generic; using System.Web; using System.Web.Mvc; using Umbraco.Web.Mvc; using umbraco.cms.businesslogic.member; using Lebsea.Site.Models; using Lebsea.Site.BusinessLogic;
/// <summary> /// Summary description for ContactUsController /// </summary> /// namespace Lebsea.Site.Controllers { public class ContactUsController : SurfaceController {
[HttpPost] public ActionResult HandleContactSubmit(ContactUsModel model) { //model not valid, do not save, but return current umbraco page if (ModelState.IsValid == false) { //Perhaps you might want to add a custom message to the TempData or ViewBag //which will be available on the View when it renders (since we're not //redirecting) return CurrentUmbracoPage(); }
var mail = new Mail.MailVariables { From = model.Email, FromName = model.Name, Content = string.Format(model.Message), Subject = "Contact mail from site", To = "[email protected]", ToName = "Site Owner Name" };
if (Mail.SendMail(mail)) {
TempData.Add("Success", true); }
return RedirectToCurrentUmbracoPage();
//Or redirect to specific page //return RedirectToUmbracoPage(12345) }
} }
Partial View File ContactUs.cshtml
@using Lebsea.Site.Controllers @model Lebsea.Site.Models.ContactUsModel @{ var formSent = false; var success = TempData["Success"]; if (success != null) { bool.TryParse(success.ToString(), out formSent); } }
@inherits Umbraco.Web.Macros.PartialViewMacroPage @using Lebsea.Site.Models @{ Html.RenderPartial("~/Views/Partials/ContactUs.cshtml", new ContactUsModel()); }
When I run the code it renders fine but when I try to submit the form I get the following and the breakpoint in my controller is not hit:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /umbraco/RenderMvc
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
If I change using (Html.BeginUmbracoForm<ContactUsController>("HandleContactSubmit")) to using (Html.BeginUmbracoForm("HandleContactSubmit", "ContactUsController")) I get the following:
Server Error in '/' Application.
Could not find a Surface controller route in the RouteTable for controller name ContactUsController
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Could not find a Surface controller route in the RouteTable for controller name ContactUsController
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: Could not find a Surface controller route in the RouteTable for controller name ContactUsController]
Umbraco.Web.Mvc.RenderRouteHandler.HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo) +1101
Umbraco.Web.Mvc.RenderRouteHandler.GetHandlerForRoute(RequestContext requestContext, PublishedContentRequest publishedContentRequest) +271
Umbraco.Web.Mvc.RenderRouteHandler.GetHttpHandler(RequestContext requestContext) +296
System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) +9770076
Umbraco.Web.UmbracoModule.RewriteToUmbracoHandler(HttpContextBase context, PublishedContentRequest pcr) +398
Umbraco.Web.UmbracoModule.ProcessRequest(HttpContextBase httpContext) +850
Umbraco.Web.UmbracoModule.<Init>b__a(Object sender, EventArgs e) +132
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
I have also tried adding the following with a Global.asax.cs file:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing;
namespace Lebsea.Site { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas();
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing;
namespace Lebsea.Site { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Right now I am just looking for anything I may have missed so any help is appreciated. I am just trying to get this simple example working so I can do more complex things with database access.
I don't think with the newer versions of Umrbaco you need to have the name of it have SurfaceController in it. In fact when I atteneded the level 2 training the one we did there did not. I did try it though and unfortunately got the same result. I even tried the following. Created a brand new project. Add the following very basic items:
Model: ContactUs.cs
using System.Web;
namespace LebseaRespUmbracoMVC.Models { public class ContactUs { public string Name { get; set; } } }
====================
Controller: ContactUsController.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Umbraco.Web.Mvc;
namespace LebseaRespUmbracoMVC.Controllers { public class ContactUsSurfaceController : SurfaceController {
[HttpPost] public ActionResult HandleContact(Models.ContactUs model) { //if the model is not valid,return current page if (!ModelState.IsValid) return CurrentUmbracoPage();
//redirect to current page to clear the form return RedirectToCurrentUmbracoPage(); } } }
@inherits Umbraco.Web.Macros.PartialViewMacroPage @using LebseaRespUmbracoMVC.Models @{ Html.RenderPartial("~/Views/Partials/ContactUs.cshtml", new ContactUs()); }
It renders fine as beofre but gives the exact same errors when trying to submit it. It is like the routing is not setup correctly or working. This is killing me and putting a very bad taste in my mouth for my first impression on MVC.
Copied my model, controller, partial view and macro partial to thr site we used at the Umbraco Level 2 training. Only thing I changed was the namespace and it worked fine. I cannot figure out what the diference is or what I am missing.
ContactUsController Code Not Fired
I am new to Umbraco and MVC and am having trouble implementing a Contact Us form. I did everything based on the example however it is like it cannot find the route to my ConactUsController. Any ideas where I should start to look beyond the basics? I have been stuck on this for over a day now :(
Hi Mark
What example is it you're refering to? And what version of Umbraco are you using?
Could you share the code you have done as well?
/Jan
I am currently using Umbraco 7.0.4.
The example I was trying to follow as well as some sample code from a recent Umbraco Level 2 class I took was:
https://umbraco.com/follow-us/blog-archive/2013/7/14/moving-from-webforms-to-mvc.aspx
The Code I have so far is the following
Model File ContactusModel.cs
using System;
using System.Collections.Generic;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
/// <summary>
/// Summary description for ContactUsModel
/// </summary>
///
namespace Lebsea.Site.Models
{
public class ContactUsModel
{
[Required]
public string Name { get; set; }
[Required]
[RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")]
public string Email { get; set; }
[Required]
public string Message { get; set; }
}
}
Controller File ContactUsController.cs
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using Umbraco.Web.Mvc;
using umbraco.cms.businesslogic.member;
using Lebsea.Site.Models;
using Lebsea.Site.BusinessLogic;
/// <summary>
/// Summary description for ContactUsController
/// </summary>
///
namespace Lebsea.Site.Controllers
{
public class ContactUsController : SurfaceController
{
[HttpPost]
public ActionResult HandleContactSubmit(ContactUsModel model)
{
//model not valid, do not save, but return current umbraco page
if (ModelState.IsValid == false)
{
//Perhaps you might want to add a custom message to the TempData or ViewBag
//which will be available on the View when it renders (since we're not
//redirecting)
return CurrentUmbracoPage();
}
var mail = new Mail.MailVariables
{
From = model.Email,
FromName = model.Name,
Content = string.Format(model.Message),
Subject = "Contact mail from site",
To = "[email protected]",
ToName = "Site Owner Name"
};
if (Mail.SendMail(mail))
{
TempData.Add("Success", true);
}
return RedirectToCurrentUmbracoPage();
//Or redirect to specific page
//return RedirectToUmbracoPage(12345)
}
}
}
Partial View File ContactUs.cshtml
@using Lebsea.Site.Controllers
@model Lebsea.Site.Models.ContactUsModel
@{
var formSent = false;
var success = TempData["Success"];
if (success != null)
{
bool.TryParse(success.ToString(), out formSent);
}
}
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@if (formSent)
{
<p>Thanks, we'll get back to you soon!</p>
}
else
{
using (Html.BeginUmbracoForm<ContactUsController>("HandleContactSubmit"))
{
@Html.LabelFor(model => model.Name)<br />
@Html.EditorFor(model => model.Name)<br />
@Html.ValidationMessageFor(model => model.Name)<br />
@Html.LabelFor(model => model.Email)<br />
@Html.EditorFor(model => model.Email)<br />
@Html.ValidationMessageFor(model => model.Email)<br />
@Html.LabelFor(model => model.Message)<br />
@Html.TextAreaFor(model => model.Message)<br />
@Html.ValidationMessageFor(model => model.Message)<br />
<p>
<input type="submit" value="Submit" />
</p>
}
}
Macro Partial ContactUs.cshtml
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@using Lebsea.Site.Models
@{
Html.RenderPartial("~/Views/Partials/ContactUs.cshtml", new ContactUsModel());
}
When I run the code it renders fine but when I try to submit the form I get the following and the breakpoint in my controller is not hit:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /umbraco/RenderMvc
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
If I change using (Html.BeginUmbracoForm<ContactUsController>("HandleContactSubmit")) to using (Html.BeginUmbracoForm("HandleContactSubmit", "ContactUsController")) I get the following:
Server Error in '/' Application.
Could not find a Surface controller route in the RouteTable for controller name ContactUsController
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Could not find a Surface controller route in the RouteTable for controller name ContactUsController
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
I have also tried adding the following with a Global.asax.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
namespace Lebsea.Site
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//WebApiConfig.Register(GlobalConfiguration.Configuration);
//FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
}
and the RouteConfig.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace Lebsea.Site
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
Right now I am just looking for anything I may have missed so any help is appreciated. I am just trying to get this simple example working so I can do more complex things with database access.
Thanks in advance for any help
I'm not entirely sure, but I think it has to be named like so:
Dunno if it helps any ;-)
I don't think with the newer versions of Umrbaco you need to have the name of it have SurfaceController in it. In fact when I atteneded the level 2 training the one we did there did not. I did try it though and unfortunately got the same result. I even tried the following. Created a brand new project. Add the following very basic items:
Model: ContactUs.cs
using System.Web;
namespace LebseaRespUmbracoMVC.Models
{
public class ContactUs
{
public string Name { get; set; }
}
}
====================
Controller: ContactUsController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Umbraco.Web.Mvc;
namespace LebseaRespUmbracoMVC.Controllers
{
public class ContactUsSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult HandleContact(Models.ContactUs model)
{
//if the model is not valid,return current page
if (!ModelState.IsValid)
return CurrentUmbracoPage();
//redirect to current page to clear the form
return RedirectToCurrentUmbracoPage();
}
}
}
=====================================================================
Partial View: ContactUs.cshtml
@model LebseaRespUmbracoMVC.Models.ContactUs
@using (Html.BeginUmbracoForm < LebseaRespUmbracoMVC.Controllers.ContactUsSurfaceController>("HandleContact"))
{
//here we will insert our form elements
<div class="editor-label">@Html.LabelFor(model => model.Name)</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<input type="submit" value="Login" />
}
================================================================
MacroPartial: ContactUs.cshtml
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@using LebseaRespUmbracoMVC.Models
@{
Html.RenderPartial("~/Views/Partials/ContactUs.cshtml", new ContactUs());
}
It renders fine as beofre but gives the exact same errors when trying to submit it. It is like the routing is not setup correctly or working. This is killing me and putting a very bad taste in my mouth for my first impression on MVC.
Copied my model, controller, partial view and macro partial to thr site we used at the Umbraco Level 2 training. Only thing I changed was the namespace and it worked fine. I cannot figure out what the diference is or what I am missing.
I finally found my issue. In my template the following code was around my macro:
<form runat="server">
</form>
After I removed it everything worked. Now on to learning more MVC and Umbraco
is working on a reply...