How do I implement two SUBMIT buttons (or more in the same partial view) hitting the same Surface controller?
Hi everybody. I'm a rookie to MVC 5 and Umbraco 7 still on my first week and my first project. Here I ran into a issue ... I'll try to explain myself.
I have a single partial view in which I can submit some data - which works fine. Now, the problem is that I need to extend my business logic and provide the ability to delete the very same object? Here is some code snippet:
My Controller looks like this ....
public class AddressSurfaceController : SurfaceController
{
public ActionResult RenderForm(Address dto)
{
return PartialView($"~/Views/Partials/Customer/_AddressSurface.cshtml", dto);
}
[HttpPost]
public ActionResult SubmitForm(Address dto)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
if (dto != null)
{
new CustomerRepository().SaveAdressDto(dto);
}
return RedirectToCurrentUmbracoPage();
}
[HttpPost]
public ActionResult Submit(Address dto)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
if (dto != null)
{
new CustomerRepository().SaveAdressDto(dto);
}
return RedirectToCurrentUmbracoPage();
}
[HttpPost]
public ActionResult Delete(Address dto)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
if (dto != null)
{
new CustomerRepository().DeleteAddressDto(dto);
}
return RedirectToCurrentUmbracoPage();
}
}
And my Partial View looks like this (some lines delete for better overview) ....
Now, the last submit button actually hits the public ActionResult SubmitForm(Address dto) as expected :-)
But if I try one of the other two buttons like <input type="submit" [email protected]("Submit") formmethod="post" class="btn btn-primary" /> or <input type="submit" [email protected]("Delete") formmethod="post" class="btn btn-danger" /> I do hit the public function in my controller ...
... but can't be redirected back to the Partial View !!! I get this exception {"Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request"}
It is the magic Html.BeginUmbracoForm, which has a hidden field which contains a hash that is used to route the posted form back to your Surface Controller Action...
... however for your additional buttons, you are setting the formaction explicitly using Url.Action (which would work in a pure mvc app) but without the hidden field Umbraco doesn't know how to route the request to the Surface Controller Action (an Umbraco thing) ...
... there are several ways around this...
but I think the simplest is to use a special Umbraco UrlHelper extension called 'SurfaceAction'...
The Umbraco source describes this as 'Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified Surface Controller.
Thanks for your answer ... looked at your suggestion but still can't work it out!
First step was looking at the [email protected]("actionName", "ctrlName") and found that any changes to this didn't make any difference, because the only action taking place in the SurfaceController is public ActionResult SubmitForm(Address dto) - which is dictated in top of the View @using (Html.BeginUmbracoForm("SubmitForm", "AddressSurface")) !!!
Next step was looking at the solution you kindly referenced by Andrey Shchekin.
Also here, the logic of Umbraco was immunne to the use of [HttpParamAction] in my controller because it never recognize the action in [email protected]("Submit", "AddressSurface") and kept looking for the action defined in top of the View @using (Html.BeginUmbracoForm("SubmitForm", "AddressSurface", FormMethod.Post))!!!
So ... could be nice just to solve this in pure HTML like you suggested in the first place.
We know that a Button always triggers a SubmitForm event - so the 'Delete' button first calls JavaScript function onClickDelAddress then triggers the SubmitForm event. In this way I can tell the Surface controller to delete a specific object.
Using other public function/methode but the SubmitForm is done with $ajax - as you can see in the first JavaScript function onClickInsertAddress. Please notice; the ajax argument 'data' must match a function/methode signature to the point otherwise $ajax can't see the function/methode!
How do I implement two SUBMIT buttons (or more in the same partial view) hitting the same Surface controller?
Hi everybody. I'm a rookie to MVC 5 and Umbraco 7 still on my first week and my first project. Here I ran into a issue ... I'll try to explain myself.
I have a single partial view in which I can submit some data - which works fine. Now, the problem is that I need to extend my business logic and provide the ability to delete the very same object? Here is some code snippet:
My Controller looks like this ....
And my Partial View looks like this (some lines delete for better overview) ....
Now, the last submit button actually hits the
public ActionResult SubmitForm(Address dto)
as expected :-)But if I try one of the other two buttons like
<input type="submit" [email protected]("Submit") formmethod="post" class="btn btn-primary" />
or<input type="submit" [email protected]("Delete") formmethod="post" class="btn btn-danger" />
I do hit the public function in my controller ...... but can't be redirected back to the Partial View !!! I get this exception
{"Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request"}
Could anyone please direct me in the right way?
Thank in advance.
Hi Lars
It is the magic Html.BeginUmbracoForm, which has a hidden field which contains a hash that is used to route the posted form back to your Surface Controller Action...
... however for your additional buttons, you are setting the formaction explicitly using Url.Action (which would work in a pure mvc app) but without the hidden field Umbraco doesn't know how to route the request to the Surface Controller Action (an Umbraco thing) ...
... there are several ways around this...
but I think the simplest is to use a special Umbraco UrlHelper extension called 'SurfaceAction'...
eg
The Umbraco source describes this as 'Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified Surface Controller.
hopefully that helps!
Otherwise in MVC you can create an ActionMethodSelectorAttribute - see http://blog.ashmind.com/2010/03/15/multiple-submit-buttons-with-asp-net-mvc-final-solution/
Hi Marc.
Thanks for your answer ... looked at your suggestion but still can't work it out!
First step was looking at the
[email protected]("actionName", "ctrlName")
and found that any changes to this didn't make any difference, because the only action taking place in the SurfaceController ispublic ActionResult SubmitForm(Address dto)
- which is dictated in top of the View@using (Html.BeginUmbracoForm("SubmitForm", "AddressSurface"))
!!!Next step was looking at the solution you kindly referenced by Andrey Shchekin.
Also here, the logic of Umbraco was immunne to the use of
[HttpParamAction]
in my controller because it never recognize the action in[email protected]("Submit", "AddressSurface")
and kept looking for the action defined in top of the View@using (Html.BeginUmbracoForm("SubmitForm", "AddressSurface", FormMethod.Post))
!!!So ... could be nice just to solve this in pure HTML like you suggested in the first place.
What am I missing?
Hi Lars
I'm facing the same issue.
Did you find out the solution? Can you share some details how to resolve this issue?
Appreciate for your help.
Hi Javafun.
I never had succes with pure HTML - so my solution was a mix of HTML and JavaScript up front calling the Surface Controller backend.
Here is some backend code - no need to show the complete implementation:
And here is some frontend code - no need to show the complete implementation:
And in my HTML code I have two buttons:
(pure HTML code is difficult to show!)
We know that a Button always triggers a SubmitForm event - so the 'Delete' button first calls JavaScript function onClickDelAddress then triggers the SubmitForm event. In this way I can tell the Surface controller to delete a specific object.
Using other public function/methode but the SubmitForm is done with $ajax - as you can see in the first JavaScript function onClickInsertAddress. Please notice; the ajax argument 'data' must match a function/methode signature to the point otherwise $ajax can't see the function/methode!
Best Regards
is working on a reply...