Problems with displaying custom form (not Umbraco Form)
I'm trying to create some custom forms in Umbraco 13.0.0, but I keep getting a "Page Not Found Cannot render the page at URL '/workorder/'. These forms were working in Umbraco 8, and I know the syntax has changed, but even when using the documentation here for Creating Forms, and here for using Surface Controllers I still get the "Page Not Found" with above error.
Here is my code so you can see what I'm trying.
WORKORDER MODEL:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Umbraco13ProjectTest.Models.Workorder
{
public class WorkorderModel
{
[Required(ErrorMessage = "Reported By is required.")]
[StringLength(75,ErrorMessage = "Reported By must be 75 characters or less.")]
[Display(Name = "Reported By:")]
public string? ReportedBy { get; set; }
[Required(ErrorMessage = "Unit is required.")]
[Display(Name = "Unit:")]
public string? Unit { get; set; }
[Required(ErrorMessage = "Facility Location is required.")]
[StringLength(150,ErrorMessage = "Facility Location must be 150 characters or less.")]
[Display(Name = "Facility Location:")]
public string? FacilityLocation { get; set; }
[Required(ErrorMessage = "Building/Room # is required.")]
[StringLength(25,ErrorMessage = "Building/Room # must be 25 characters or less.")]
[Display(Name = "Building/Room #:")]
public string? BuildingRoomNumber { get; set; }
[Required(ErrorMessage = "Phone # for Primary POC is required")]
[StringLength(15,ErrorMessage = "Phone # for Primary POC must be 15 characters or less.")]
[Display(Name = "Phone # for Primary POC:")]
public string? PrimaryPocPhone { get; set; }
[Required(ErrorMessage = "Email for Primary POC is required")]
[StringLength(150,ErrorMessage = "Email for Primary POC must be 150 characters or less.")]
[Display(Name = "Email for Primary POC:")]
[EmailAddress]
public string? PrimaryPocEmail { get; set; }
[Required(ErrorMessage = "Phone # for Secondary POC is required")]
[StringLength(15,ErrorMessage = "Phone # for Secondary POC must be 15 characters or less.")]
[Display(Name = "Phone # for Secondary POC:")]
public string? SecondaryPocPhone { get; set; }
[Required(ErrorMessage = "Email for Secondary POC is required")]
[StringLength(150,ErrorMessage = "Email for Secondary POC must be 150 characters or less.")]
[Display(Name = "Email for Secondary POC:")]
[EmailAddress]
public string? SecondaryPocEmail { get; set; }
[Required(ErrorMessage = "Authorized By is required")]
[StringLength(150,ErrorMessage = "Authorized By must be 150 characters or less.")]
[Display(Name = "Authorized By:")]
public string? AuthorizedBy { get; set; }
[Required(ErrorMessage = "Priority Level is required")]
[Display(Name = "Priority Level:")]
public string? PriorityLevel { get; set; }
[Required(ErrorMessage = "Work Request Details are required")]
[StringLength(2000,ErrorMessage = "Work Request Details must 2000 characters or less.")]
[Display(Name = "Work Request Details:")]
public string? WorkRequestDetails { get; set; }
[Display(Name = "Date Submitted:")]
public string? DateSubmitted { get; set; }
}
}
WORKORDER CONTROLLER:
using Microsoft.AspNetCore.Mvc;
using System.Net.Mail;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Web.Website.Controllers;
using Umbraco13ProjectTest.Models.Workorder;
namespace Umbraco13ProjectTest.Controllers;
public class WorkorderController : SurfaceController
{
private const string PVF = "~/Views/Partials/Forms/Workorder/";
private const string WEBMASTER_EMAIL = "[email protected]";
private const string TEST_EMAIL = "[email protected]";
private const string WORKORDER_EMAIL = "[email protected]";
public FmoWorkorderController(IUmbracoContextAccessor umbracoContextAccessor,IUmbracoDatabaseFactory databaseFactory,ServiceContext services,AppCaches appCaches,IProfilingLogger profilingLogger,IPublishedUrlProvider publishedUrlProvider) : base(umbracoContextAccessor,databaseFactory,services,appCaches,profilingLogger,publishedUrlProvider){}
public ActionResult RenderForm()
{
return PartialView(PVF + "_WorkorderPartial.cshtml");
}
[HttpPost]
//[CaptchaValidator]
[ValidateAntiForgeryToken]
public IActionResult Submit(WorkorderModel w)
{
if(ModelState.IsValid)
{
if(w.ReportedBy?.ToUpper() == "TEST")
{
//SendTestEmail(w);
}
else
{
SendWorkorder(w);
//SendToWebmaster(w);
}
TempData["WorkorderSuccess"] = true;
return RedirectToCurrentUmbracoPage();
}
return CurrentUmbracoPage();
}
private void SendWorkorder(WorkorderModel w)
{
string Email_Body = GetEmailBody(w);
MailMessage message = new MailMessage(w.PrimaryPocEmail,WORKORDER_EMAIL)
{
Subject = "Priority Level: " + w.PriorityLevel + " - Work Order Request",
IsBodyHtml = true,
Body = Email_Body
};
SmtpClient client = new SmtpClient("smtpa...",25);
client.Send(message);
}
private string GetEmailBody(WorkorderModel w)
{
return "I WON'T BORE YOU WITH THE EMAIL DETAILS";
}
}
WORKORDER VIEW:
@* @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage *@
@inherits UmbracoViewPage<Umbraco13ProjectTest.Models.Workorder>
@model Umbraco13ProjectTest.Models.Workorder.WorkorderModel
@* @using reCAPTCHA.MVC; *@
@{
var officeGroup = new SelectListGroup() { Name = "Offices" };
//THERE ARE MORE GROUPS BUT FOR BREVITY THEY ARE LEFT OFF
var Units= new List<SelectListItem>()
{
new SelectListItem() { Text="Office 1, Value="Office 1", Group=officeGroup},
new SelectListItem() { Text="Office 2", Value="Office 2", Group=officeGroup},
new SelectListItem() { Text = "Office 3", Value = "Office 3", Group=officeGroup},
new SelectListItem() { Text="Office 4", Value="Office 4", Group=officeGroup},
new SelectListItem() { Text="Office 5", Value="Office 5", Group=officeGroup},
}
}
<section id="#" style="background-color: #fff;">
<div class="container">
<div class="heading-wrapper text-center">
<h1 class="heading">Work Order Request</h1>
<div class="squares">
<span class="square"></span>
<span class="square"></span>
<span class="square"></span>
<span class="square"></span>
<span class="square"></span>
<span class="square"></span>
</div>
</div>
@using(Html.BeginUmbracoForm("Submit","WorkorderSurface", FormMethod.Post,new { IDataTokensMetadata = "workorder"}))
{
@Html.AntiForgeryToken()
<div>
@Html.ValidationSummary(false,"",new { @class = "red bolder" })
@* REPORTED/AUTHORIZED BY *@
<div class="form-group row no-side-margin">
<div class="col-md-6 padding">
@Html.LabelFor(model => model.ReportedBy,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.ReportedBy,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.ReportedBy,"",new { @class = "red" })
</div>
</div>
<div class="col-md-6 padding">
@Html.LabelFor(model => model.AuthorizedBy,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.AuthorizedBy,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.AuthorizedBy,"",new { @class = "red" })
</div>
</div>
</div>
@* PRIMARY PHONE/EMAIL *@
<div class="form-group row no-side-margin">
<div class="col-md-6 padding">
@Html.LabelFor(model => model.PrimaryPocPhone,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.PrimaryPocPhone,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.PrimaryPocPhone,"",new { @class = "red" })
</div>
</div>
<div class="col-md-6 padding">
@Html.LabelFor(model => model.PrimaryPocEmail,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.PrimaryPocEmail,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.PrimaryPocEmail,"",new { @class = "red" })
</div>
</div>
</div>
@* SECONDARY PHONE/EMAIL *@
<div class="form-group row no-side-margin">
<div class="col-md-6 padding">
@Html.LabelFor(model => model.SecondaryPocPhone,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.SecondaryPocPhone,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SecondaryPocPhone,"",new { @class = "red" })
</div>
</div>
<div class="col-md-6 padding">
@Html.LabelFor(model => model.SecondaryPocEmail,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.SecondaryPocEmail,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SecondaryPocEmail,"",new { @class = "red" })
</div>
</div>
</div>
@* OFFICE/LOCATION/BUILDING-ROOM NUMBER *@
<div class="form-group row no-side-margin">
<div class="col-md-4 padding">
@Html.LabelFor(model => model.Unit,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.DropDownListFor(model => model.Unit,Units,"--Make a selection--",new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Unit,"",new { @class = "red" })
</div>
</div>
<div class="col-md-4 padding">
@Html.LabelFor(model => model.FacilityLocation,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.FacilityLocation,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FacilityLocation,"",new { @class = "red" })
</div>
</div>
<div class="col-md-4 padding">
@Html.LabelFor(model => model.BuildingRoomNumber,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
@Html.EditorFor(model => model.BuildingRoomNumber,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.BuildingRoomNumber,"",new { @class = "red" })
</div>
</div>
</div>
@* PRIORITY LEVEL *@
<div class="form-group row no-side-margin">
@Html.LabelFor(model => model.PriorityLevel,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding">
<label class="control-label col-md-12 padding">
@Html.RadioButtonFor(model => model.PriorityLevel,"1") Priority 1 - Emergency - Immediate Action Required<br />
<p class="margin-left-20">
Examples - Life/Safety Health Issues. Building Integrity-freeze, fire, or flood danger. All call-outs. Refrigeration repairs so food does not spoil. Air Conditioner in switch room of ANCA or in USP computer area. Reset breakers/equipment after power failure. No Heat in building (Vs Room)? Gas/Burning odor. Oil spills or gas leaks. Building broken into(need to secure). Fire alarms. Reset Earthquake valve. Questionable: Doors won't lock, let contractor into building.
</p>
</label>
<label class="control-label col-md-12 padding">
@Html.RadioButtonFor(model => model.PriorityLevel,"2") Priority 2 - Preventative Maintenance<br />
<p class="margin-left-20">
Used only for PM work orders
</p>
</label>
<label class="control-label col-md-12 padding">
@Html.RadioButtonFor(model => model.PriorityLevel,"3") Priority 3 - Call worker off current job<br />
<p class="margin-left-20">
Examples - Lights out over work area. Toilet plugged but other available. Odor in building due to dried out drains, clogged filters, etc. Appliance not working in CC620 (dishwasher, stoves, etc.). Questionable: No heat in rooms, no air to work area., doors that will not close/open, keys stuck in locks. Request for keys usually need them the same day.
</p>
</label>
<label class="control-label col-md-12 padding">
@Html.RadioButtonFor(model => model.PriorityLevel,"4") Priority 4 - Scheduled corrective action<br />
<p class="margin-left-20">
Examples - Repair hole in wall. Repair loose carpeting. Replace ceiling tiles. Replace exterior lamps on hangar.
</p>
</label>
<label class="control-label col-md-12 padding">
@Html.RadioButtonFor(model => model.PriorityLevel,"5") Priority 5 - Would not make a special trip<br />
<p class="margin-left-20">
Examples - Complete during next scheduled PM. Applies to most out of town trips, replace fuel tank sensors, mothball facilities.
</p>
</label>
@Html.ValidationMessageFor(model => model.PriorityLevel,"",new { @class = "red" })
</div>
</div>
@* WORK REQUEST DETAILS *@
<div class="form-group row no-side-margin">
@Html.LabelFor(model => model.WorkRequestDetails,htmlAttributes: new { @class = "control-label col-md-12 padding required" })
<div class="col-md-12 padding text-center">
@Html.TextAreaFor(model => model.WorkRequestDetails,10,99,new { htmlAttributes = new { @class = "form-control" } })
</div>
@Html.ValidationMessageFor(model => model.WorkRequestDetails,"",new { @class = "red" })
</div>
<hr />
@* SUBMIT REQUEST BUTTON *@
<div class="form-group row text-center">
<input type="hidden" id="website" name="website" /><br />
@* <div align="center">
@Html.Recaptcha()
</div><br /> *@
<button type="submit" class="btn btn-primary btn-lg margin-bottom">
<i class="fas fa-paper-plane"></i> Send Request
</button>
</div>
</div>
}
</div>
</section>
WORKORDER TEMPLATE:
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@{
Layout = "_DefaultBannerLayout.cshtml";
}
//I TRIED THIS AND STILL GOT THE ERROR
@* <div class="container">
@if (TempData["WorkorderSuccess"] != null && (bool)TempData["WorkorderSuccess"])
{
<div class="row margin-top-20 margin-bottom-20 text-center">
<div class="margin-top-20 margin-bottom-20">
<div class="bg-success">
<div class="margin-top-20 margin-bottom-20">
<h2 class="margin-top-25 margin-bottom-25">Your request was sent successfully</h2>
</div>
</div>
</div>
</div>
}
else
{
Html.RenderPartial("~/Views/Partials/Forms/Workorder/_WorkorderPartial.cshtml", new Workorder());
}
</div> *@
//THIS IS HOW IT WAS DONE IN UMBRACO 8
<div class="container">
@if(TempData["WorkorderSuccess"] != null && (bool)TempData["WorkorderSuccess"])
{
<div class="row margin-top-20 margin-bottom-20 text-center">
<div class="margin-top-20 margin-bottom-20">
<div class="bg-success">
<div class="margin-top-20 margin-bottom-20">
<h2 class="margin-top-25 margin-bottom-25">Your request was sent successfully</h2>
</div>
</div>
</div>
</div>
}
else
{
//THIS TOO WAS UMBRACO 8
@*Html.RenderAction("RenderForm","WorkorderSurface");*@
//I'VE ALSO TRIED THIS
Html.RenderPartial("~/Views/Partials/Forms/Workorder/_WorkorderPartial.cshtml");
}
</div>
Please help as I need to get several new websites up that require the same features before Umbraco 8 End-of-life in February.
Problems with displaying custom form (not Umbraco Form)
I'm trying to create some custom forms in Umbraco 13.0.0, but I keep getting a "Page Not Found Cannot render the page at URL '/workorder/'. These forms were working in Umbraco 8, and I know the syntax has changed, but even when using the documentation here for Creating Forms, and here for using Surface Controllers I still get the "Page Not Found" with above error.
Here is my code so you can see what I'm trying.
WORKORDER MODEL:
WORKORDER CONTROLLER:
WORKORDER VIEW:
WORKORDER TEMPLATE:
Please help as I need to get several new websites up that require the same features before Umbraco 8 End-of-life in February.
is working on a reply...