Lukas25 Lukas25 - 2 months ago 21
Ajax Question

Umbraco route definition-ajax form

Hi :) I've got error "Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request" and return this wrong peace of code - "return RedirectToCurrentUmbracoPage();". After seding ajax form.

This is my cotroller:

public class ContactController : Umbraco.Web.Mvc.SurfaceController
{
private string GMAIL_SERVER = "smtp.gmail.com";
private int PORT = 587;

[ChildActionOnly]
public ActionResult ContactForm()
{
var model = new ContactFormModel()
{
Email = "",
Name = "",
Subject = "",
Message = ""
};

return PartialView("ContactForm", model);
}

[NotChildAction]
[HttpPost]
public ActionResult ContactForm(ContactFormModel model)
{
var fromAddress = new MailAddress("xxx@gmail.com", model.Name);
var toAddress = new MailAddress("xxx@gmail.com", "To Name");
string fromPassword = "xxx";
string subject = model.Subject;
string body = model.Message;

var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword),
Timeout = 20000
};

if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}

var message = new MailMessage(fromAddress, toAddress)
{
Subject = model.Subject,
Body = "test"
};
smtp.Send(message);

return RedirectToCurrentUmbracoPage();
}
}


and this form code:

@using (Ajax.BeginForm("ContactForm" ,"Contact", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace }))
{
@Html.TextBoxFor(m => m.Name, null, new { name = "name", id = "name", placeholder = "Name" })
@Html.ValidationMessageFor(m => m.Name)
@Html.TextBoxFor(m => m.Email, null, new { name = "email", id = "email", placeholder = "Email address" })
@Html.ValidationMessageFor(m => m.Email)
@Html.TextBoxFor(m => m.Subject, null, new { name = "subject", id = "subject", placeholder = "Subject" })
@Html.ValidationMessageFor(m => m.Subject)
@Html.TextAreaFor(m => m.Message, new { rows = "", cols = "", name = "message", id = "message", placeholder = "Your message" })
@Html.ValidationMessageFor(m => m.Message)
<input type="submit" id="contact-submit" value="SEND MESSAGE">
}

Answer

first of all, we need to understand what we want to achieve during this submission. Ajax request is not a part of typical page request and Umbraco Context is not passed / populated during this one. If we want to reload / refresh the same page, we can use the Javascript result from action and perform simple reload e.g.

return JavaScript("location.reload(true)");

If we want to play with the Umbraco Context (Url or anything else), we can initiate UmbracoHelper manually and do whatever we want to do with it:

var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
var node = umbracoHelper.TypedContent(nodeId);
//...

or just use a WebAPI controllers with Umbraco implementation / wrapper, about which you can read more here: https://our.umbraco.org/documentation/reference/routing/webapi/.

If it would be a typical SurfaceController action (not Ajax call), we can use all possible redirects and methods available in Umbraco wrapper (check: https://our.umbraco.org/documentation/reference/templating/mvc/forms).

We can also return any PartialView, Content or even JSON if it's required after the positive submission of the form. And this is in my opinion the best solution in this case. In your case:

[NotChildAction]
[HttpPost]
public ActionResult ContactForm(ContactFormModel model)
{
    var fromAddress = new MailAddress("xxx@gmail.com", model.Name);
    var toAddress = new MailAddress("xxx@gmail.com", "To Name");
    string fromPassword = "xxx";
    string subject = model.Subject;
    string body = model.Message;

    var smtp = new SmtpClient
    {
        Host = "smtp.gmail.com",
        Port = 587,
        EnableSsl = true,
        DeliveryMethod = SmtpDeliveryMethod.Network,
        Credentials = new NetworkCredential(fromAddress.Address, fromPassword),
        Timeout = 20000
    };

    if (!ModelState.IsValid)
    {        
        return PartialView("_Error");
    }

    var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = model.Subject,
        Body = "test"
    };
    smtp.Send(message);

    return PartialView("_Success");
}

Hope that it will help you!

Comments