Html.BeginForm Routing In Page Type

 

Hello,

Sorry if this question has been asked before. I haven't been able to find the kind of solution I'm looking for.

I've hardcoded a MVC form that uses an HTTP POST method to communicate with an API to an external database within a new Page Type. 

@using (Html.BeginForm([actionName], [controllerName], FormMethod.Post, new { role = "form" }))
{
@Html.AntiForgeryToken()

//Form

}

Traditionally in MVC I'd use Html.BeginForm to POST the submitted form values to the database. Unfortunately because of the way routing is set up in Episerver I'm not sure how to successfully submit the form without running into the error HTTP Error 404.0 - Not Found after clicking submit. Is there a straightforward way to set up the routing for the form within Episerver to successfully submit POST method forms?

Much appreciated.

#203286
Edited, Apr 15, 2019 18:52
Stefan Holm Olsen
Member since: 2013
 

Have you mapped any custom MVC routes in your project?

Episerver runs on top of MVC. So you can  map your own route to your controller. I prefer to do this in an InitializationModule.

I slso recommend that you add only a specific route for this one controller (specify the default controller name in that route). You might not want to map a default MVC route, as it can mess things up with Episerver’s routing.

#203288
Apr 15, 2019 21:15
 

Hey Stefan,

I don't beleive I've mapped any custo routes just created a standard MVC page. Within the View I've indicated the action method I want to call. Is an Initialization Module necessary for this?

How would I go about adding a specific route?

#203290
Apr 15, 2019 22:52
Stefan Holm Olsen
Member since: 2013
 

Then chances are you haven't set it up yet.

Actually, you can just put it in your Global class (provided it inherits from Episerver.Global). Something like this (fill in the placeholders):

protected override void OnRoutesRegistered(RouteCollection routes)
{
    routes.MapRoute(
        "<ROUTE_NAME>",
        "<URL_TO_CONTROLLER>/{action}",
        new { controller = "<YOUR_CONTROLLERNAME>", action = "Index" });

    base.OnRoutesRegistered(routes);
}

By specifying the URL and the controller name, you make sure this route can only be used for this purpose. Then it won't interfere with Episerver content routes.

With this in place, you can even render your form using the route name instead of the controller and action pair. Like this:

using (Html.BeginRouteForm("<ROUTE_NAME>", FormMethod.Post, new { role = "form" }))
{
   // Your form content
}
#203297
Apr 16, 2019 7:35
 

Thanks for the information Stefan.

Would the OnRoutesRegistered function go inside of the Global.asax file or can I put in anywhere within the solution?

#203330
Edited, Apr 16, 2019 19:31
valdis iljuconoks
Member since: 2011
 

just wondering why you can't use page external url (aka friendly url) and post form there. then have index action on page type's controller (attributed with [HttpPost] attribute) and receive submitted view model and do the saving in the database there? why you are posting to actual mvc controller?

#203334
Apr 16, 2019 21:58
 

Hey Valdis thanks for the response,

Sorry I'm only familiar with the standard way of creating page types in Episerver so I'm not too familiar with page external URL method. Is there documentation that you know of which can help me understandwhat you're suggesting more. I'm fairly new to Episerver.

Regarding why I'm posting to the MVC controller, the submitted information has to be passed to the action within the controller in order to the process to work. Isn't that the common way HttpClient method is used with Html.Beginform? Maybe I'm not completely understanding what you're saying but the approach I'm using works in a typical MVC application.

#203336
Apr 16, 2019 22:07
valdis iljuconoks
Member since: 2011
 

so basically why you "can't" post to /{controller}/{action} by default is that episerver is "trying" to handle incoming requests and route to actual page types. 

oen way around this would be to create a form and set action to the friendly url of the page:

<form action="post" action="@Url.ContentUrl(CurrentPage)" ...>
...
</form>

`Url` is helper coming from Mvc - but there are Episerver specific extension methods around it.

if you don't like "manual" form element creation - you can create "fluent api" - that generates that element via Mvc (like for example using FormHelpers).

but... I would strongly recommend you to go through AlloyTech demo site (can be created via Visual Studio extension - https://marketplace.visualstudio.com/items?itemName=EPiServer.EpiserverCMSVisualStudioExtension) and really dig every source line of the sample site. Dig it and be confident that you understand how that site is working.

That will help you great deal!

#203337
Apr 16, 2019 22:34
 

Thanks again Valdis,

I think I want to stick to the Html.BeginForm method as it serves the purpose best for HttpClient POST that I know of.

@using (Html.BeginForm([actionName], [controllerName], new { language = ContentLanguage.PreferredCulture.Name }, FormMethod.Post, new { role = "form" }))

{

//Form

}

When I use @Url.ContentUrl(CurrentPage) in my View I get the error that it doesn't exist in the current context.

I will definitely check out the AlloyTech example at some point but right now I'm in the very last stage of completing the form and would like to see that through first.

#203358
Edited, Apr 17, 2019 17:52
valdis iljuconoks
Member since: 2011
 

regarding "does not exist in current context" - you most probably need tp "bring" Episerver page instance (one that you can "request" in your mvc action with argument name "currentPage") down to view - via view model, view data or any other mechanism.

#203364
Apr 18, 2019 9:19
 

Thanks a lot Valdis I will try that.

#203375
Apr 18, 2019 16:32