The other day I was looking for a way to handle a common dilemma with MVC forms and Sitecore. It goes like this: Put an “Add To Favorites” button in the page header and an email subscription form in the footer. Both do form posts. If the developer uses a common MVC form technique (reusing the action name, just decorating [HttpGet] or [HttpPost]) then both forms get submitted. Sign up for the newsletter and voila, you’ve favorited the page! Whoops. This is because the HTTP post verb is global to the page request.
I’ve worked out a fairly elegant way to handle this, curious your thoughts. The idea is we create a form token that is submitted with the form. If we hit the post action for a form that was not submitted, we return the HttpGet action instead. And of course if the token is valid, we allow the post action to process.
Here is an example implementation.
1. In the controller post actions we add a custom attribute filter named “[MultiformPostProtection]”:
================================
ExampleController.cs
================================
2. In the markup we call a custom HtmlHelper “@Html.MultiformPostProtection()” that renders the appropriate form token (based on MVC action name) as a hidden input field.
================================
FormA.cshtml
================================
================================
FormB.cshtml
================================
And that’s it, magical!
If you use this for every form component, they can all co-exist on the same page and not conflict with each other.
And of course, the code to make it all happen; you’ll need this somewhere in your solution:
================================
MultiformPostProtectionExtension.cs
================================
UPDATE:
Since posting this solution I have learned of earlier posted solutions to this issue: Click Here
Sitecore Habitat also has a helper method Html.AddUniqueFormId(): Click Here
Thanks to the community for being so active and helpful!