umbraco / Umbraco-CMS

Umbraco is a free and open source .NET content management system helping you deliver delightful digital experiences.
https://umbraco.com
MIT License
4.49k stars 2.69k forks source link

Unable to use form with Surface Controller within a custom route #13333

Closed callumbwhyte closed 1 year ago

callumbwhyte commented 2 years ago

Which Umbraco version are you using? (Please write the exact version, example: 10.1.0)

v10.3.1

Bug summary

If you register a custom route with MapControllerRoute, mapped to an UmbracoPageController per the docs, and somewhere on the resulting page add a form (i.e. a surface controller called from Html.BeginUmbracoForm) the page simply posts back to itself and never hits the controller.

This is the case regardless of if an Umbraco context is applied.

Unless I'm missing something glaringly obvious, it doesn't seem this has worked since v9 - or at least isn't something that is supported (but without a reasonable alternative?). I don't believe this was to case in V8 and prior as we certainly had forms working in custom routes.

Specifics

Diving a little deeper into the inner workings of Umbraco's request pipeline, it seems the UmbracoRouteValueTransformer is responsible for assigning the correct route values to regular requests. This is registered with a wildcard dynamic route: "/{slug*}"

This class handles creating the routing request, and checks to see if any values are being posted. This method parses the ufprt field in the request and determines the correct controller etc to route the request to the correct controller: https://github.com/umbraco/Umbraco-CMS/blob/v11/contrib/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs#L147

However, custom routes do not go through the UmbracoRouteValueTransformer. If ForUmbracoPage is used these go through the UmbracoVirtualPageFilter but this only applies the very basic values to handle rendering a page.

The docs alludes to having a "custom route, controller, even middleware, to manually assign the UmbracoRouteValues". One option might be to register as a dynamic route (like Umbraco does) and extend the UmbracoRouteValueTransformer to apply the desired custom routing logic, but this class is largely private / internal so isn't easy to affect the logic. Basically this approach only works if you want to let Umbraco handle the content / template assignment etc. The methods relating to handling form posts are internal so not easy to call upon.

Steps to reproduce

Map a custom route with the IEndpointBuilder:

builder.MapControllerRoute(
    "Custom Route",
    "/my-route/{action}/{id?}",
    new { Controller = "CustomController", Action = "Index" }
);

Create a dummy controller:

public class CustomController : UmbracoPageController
{
    public IActionResult Index()
    {
        return View("CustomView");
    }
}

Create a simple SurfaceController to handle submitting a form:

public class CustomFormController : SurfaceController
{
    [HttpPost]
    public IActionResult Submit()
    {
        return Redirect("/");
    }
}

And create a simple Razor view that posts to the controller:

@using (Html.BeginUmbracoForm("Submit", "CustomForm"))
{
    <input type="submit" name="Submit" value="Submit" />
}

Navigate to the custom route ("/my-route/Index" in this case) and submit the form. This results in the page reloading, and no breakpoints inside the SurfaceController being hit. The expected behaviour would be a redirect to "/".

github-actions[bot] commented 2 years ago

Hi there @callumbwhyte!

Firstly, a big thank you for raising this issue. Every piece of feedback we receive helps us to make Umbraco better.

We really appreciate your patience while we wait for our team to have a look at this but we wanted to let you know that we see this and share with you the plan for what comes next.

We wish we could work with everyone directly and assess your issue immediately but we're in the fortunate position of having lots of contributions to work with and only a few humans who are able to do it. We are making progress though and in the meantime, we will keep you in the loop and let you know when we have any questions.

Thanks, from your friendly Umbraco GitHub bot :robot: :slightly_smiling_face:

justin-nevitech commented 2 years ago

Hi @callumbwhyte

I'm pretty certain this is the same issue as this one:

https://github.com/umbraco/Umbraco-CMS/issues/13017

I did submit a PR for a fix back on the 3rd October but it's not been merged yet...

nikolajlauridsen commented 1 year ago

Hey Callum, I'm going to go ahead and close this one since it seems like a duplicate, it does however look like there's some action going on the other issues, so that's good new 😄