I had the same problem a few days ago. Seems putting the form element in the block makes the URL not point to an EPiServer page. I hade to put the @using (Html.BeginForm
statement on the page, surronding the block view. I found a few blog posts out there concerning forms in blocks but none helped me much.
I guess you have to find some smart way to solve routing between the page controller and the block controller to get it working (if you can't live with putting the post logic in the page controller and the BeginForm on the page view).
Try these
1. Check the HTML of rendered page and see what is action path of the page
2. Move the View in Shared Folder
3. @using (Html.BeginForm("Send", "ContactFormBlock", new {language= ContentLanguage.PreferredCulture.Name}))
Regards
/K
BeginForm doesnt know about EPiServer page language.
Try the HtmlHelper described here http://www.danielnordmark.se/language-specific-forms-episerver-7/
When the POST goes to "/ContactFormBlock/Send", EPiServer cannot know which "currentBlock" instance you were POST'ing from, so it cannot bind that parameter In your Send action.
Thanks for the fast replies, it's much appreciated.
I tried adding the language branch but that didn't help.
I have now stumbled upon another, more grave bug. When I have multiple form block on the same page, the post for one form triggers them all.
How do solve this? Is there any way to pass along some unique ID for the post?
Yes, but I can't get my head around how I would route with page and block controllers.
Me neither, that's why I gave up and put the form tag on the page view. If you have multiple form blocks, you need to surround each block with its own form tag in the page view to avoid posting all forms on the page. You also need to put a submit button for each block inside each form.
I guess there mightbe a better way, where you can have the block handle each form itself, but in my case I don't have the time to figure it out. Please let me know if you find a way!
Hannes, did you ever find a solution to this? Where the Block controller can handle the post?
Hi, from MVC perspective any incoming form submit request safely mapps to controller and action that should be invoked.
If you already prelimenary know what kind of block instances will be used on the page, you could get an idea from my solution (we had defined list of the possible form blocks on the page - we knew already that the same form will be used 3 times for instance to submit different stuff to the server):
a) Add secret property in block and expose it in templates (like hidden field)
b) Have multiple actions to handle each action in controller
c) Add attribute to each action with required matched secret field (hidden field in template):
[HttpPost] [ActionName("Index")] [FormValueRequired("HiddenField1")] public async Task<ActionResult> Action1(BlaBlaPage currentPage, [HttpPost] [ActionName("Index")] [FormValueRequired("HiddenField2")] public async Task<ActionResult> Action2(BlaBlaPage currentPage, [HttpPost] [ActionName("Index")] [FormValueRequired("HiddenField3")] public async Task<ActionResult> Action3(BlaBlaPage currentPage,
Attribute itself:
public class FormValueRequiredAttribute : ActionMethodSelectorAttribute { private readonly FormValueRequirement _requirement; private readonly string[] _submitButtonNames; public FormValueRequiredAttribute(params string[] submitButtonNames) : this(FormValueRequirement.Equal, submitButtonNames) { } public FormValueRequiredAttribute(FormValueRequirement requirement, params string[] submitButtonNames) { //at least one submit button should be found _submitButtonNames = submitButtonNames; _requirement = requirement; } public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { foreach (var buttonName in _submitButtonNames) { try { var value = ""; switch (_requirement) { case FormValueRequirement.Equal: { //do not iterate because "Invalid request" exception can be thrown value = controllerContext.HttpContext.Request.Form[buttonName]; } break; case FormValueRequirement.StartsWith: { foreach (var formValue in controllerContext.HttpContext.Request.Form.AllKeys) { if (formValue.StartsWith(buttonName, StringComparison.InvariantCultureIgnoreCase)) { value = controllerContext.HttpContext.Request.Form[formValue]; break; } } } break; } if (!String.IsNullOrEmpty(value)) { return true; } } catch (Exception exc) { //try-catch to ensure that Debug.WriteLine(exc.Message); } } return false; } }
I think this post could be good to read about this:
http://thisisnothing.nystrom.co.nz/2013/11/19/using-custom-forms-in-an-episerver-mvc-block-template/
I have a block for contact form but I cannot get the post to work. Whenever I try to post I get a 404 not found.
My form view is quite simple as I have not yet added any fields.
The controller:
The model: (the attached file property is not used, but will be in the future)
The block is placed on a page with the URL localdev.se/sv/mmx.
When I try to post the form it redirects to localdev.se/ContactFormBlock/Send and gets a 404 not found.
What have I missed? Is there any custom routing to be done?
Thanks for helping.