BeginForm v. BeginFormAntiForgeryPost

Topics: Troubleshooting, Writing modules
Nov 22, 2011 at 5:17 PM
Edited Nov 22, 2011 at 5:25 PM

I originally thought I had some validation problems worked out but started to run into weird behavior. I've now noticed what is the cause of this behavior: being logged in v. being logged out.

I have a module with a form which originally used @using (Html.BeginFormAntiForgeryPost()). I realized that my form was throwing an improper validation error by simply signing in to Orchard. If I was logged in to Orchard then the form validated and everything worked out fine. If I logged out and went back to the form, it would again throw an invalid validation error (i.e., error if fields left blank, populate fields, still throws error after submission).

If I use just @using (Html.BeginForm()), then I get the 

A required anti-forgery token was not supplied or was invalid.

error.

The form is not saving anything to the DB, it's just taking in inputs to pass a calculation using some logic based on user input. Any thoughts?

Nov 22, 2011 at 10:09 PM

Does anyone have any ideas about this problem? Sorry if it's an easy fix or if I am not explaining myself well.

I have tried a lot of different combinations of things related to using either BeginFormAntiForgeryPost vs. BeginForm and nothing seems to work.

My module is outside of the normal Orchard paradigm, I guess. I am using a Layout Filter and routes.cs to basically serve up a page.

When I am logged in the form works fine (validation, submission), but when I am logged out it will not properly validate.

Any help is much appreciated.

Coordinator
Nov 22, 2011 at 11:30 PM

A layout filter and routes? Why not a simple controller?

Nov 23, 2011 at 4:15 PM

Thanks for the reply. I was following the Hello World Module documentation and created a route and controller to serve up a page. I saw another post here about using a layout filter in order to prevent default content from appearing on the pages I served up. Still not sure how to get around this problem. I am not saving data so I thought creating a driver and/or handler would be overkill, but maybe my problem lies in the fact that I am not injecting my content into any zones?

Nov 23, 2011 at 4:24 PM

Which "default content" are you trying to prevent? With a Controller you don't need to inject anything anywhere.

Nov 23, 2011 at 4:35 PM
Edited Nov 23, 2011 at 4:36 PM

I am using one of the themes that ships with Orchard.Web. If I put content in, say "AsideSecond", and make the layer "default" then it will appear in the content my module serves up. Because I am using the entire width of the page with my module, that default "AsideSecond" content appears "under" my content. I just used the layout filter to basically have a layout file specific to my module, and it strips out all the zones except the header/footer. Is this layout.cshtml file specific to my module what is causing my BeginForm v. BeginFormAntiForgeryPost problem? I basically copied my theme's layout.cshtml file and commented out the html for zones that I didn't want to use (except the header and footer).

I guess I could avoid using the "default" layer, create a new modified "default" layer that does not appear in the module's pages, but that doesn't seem to get around my problem.

I've tried a lot of variations to get this to work. I've even used "AntiForgery: disabled" in my module.txt file.

I've looked at some other modules (contact forms) to see how I can do this properly, but I've not had any luck.

Nov 23, 2011 at 4:56 PM

The easy fix to the anti-forgery issue is to disable anti-forgery in your Module.txt, although this leaves you more open to certain types of XSS (cross-site scripting) attacks. Whether this is a problem depends on how security-critical your module is.

I wonder, are you using some form of Cache or even the Warmup module? They can cause issues with anti-forgery (otherwise your original scenario with Html.BeginFormAntiForgeryPost should have worked...)

Regarding your layout, you are better off creating a custom layer rule, so you have a widget layer that will show just on the pages you want. Stripping out the zones from a filter works, certainly, but it doesn't sound optimal.

Nov 23, 2011 at 5:08 PM

The module itself is not critical. It just allows users to make some selections, and then based on those inputs spits out a calculation.

I am using the Contrib.Cache and the Orchard.Warmup modules. Now, I presume I don't want to (or cannot) disable those modules. Cache showed all the pages in my module under my modules name. I input "0" on each page to disable. Also, on the top I input /MyModule/ as a path to ignore. For Warmup I have nothing listed in the path box, so I presume nothing is being warmed up there. Let me see if the Cache thing works.

I think I've confused the conversation with the discussion about layout. The filter.cs idea I got from a post on here that led to one of Bertrand's blogs. Basically, that filter just serves up a layout.cs file specific to a module so that you can alter the layout of pages outside of a normal theme without specifically having another website under the multi-tenancy.  I see your point about the custom layer rule. However, following the Hello World tutorial I just went that route with serving up a page that did not get put into a zone.

Nov 23, 2011 at 5:24 PM
Edited Nov 23, 2011 at 5:26 PM

Thanks for the help! Fiddling with the Contrib.Cache module as I described above helped.

I can use @ using (Html.BeginFormAntiForgeryPost()) { . . . }

I put the module.txt file back to "AntiForgery: enabled" and it still worked. I can be logged out and submit the form (with validation - not client side), and I can log in and do the same. 

I had been wiping my browser's cache to no avail and never thought to go to the settings for the Cache module in the Dashboard!

Now to tackle getting these pages into the Orchard paradigm so I can avoid using that filter. :)