Has anyone had to deal with multiple AntiForgeryTokens on a child view of a master page? The scenario I am thinking about is as follows:
The view contains a Form with an AntiForgeryToken rendered as a hidden field.
The view is contained by a master page that has another AJAX submitted form.
The issue here is that I need to encapsulate the hidden field in the Form and at the same time, I need to render another token for submission on the AJAX submitted form in the master page. I can't make any assumptions that a token will be rendered in the child page since the child page may not have a form on it.
My first thought would be to render a single global AntiForgeryToken for the entire page that all posts used, but then the forms would not post the token as the hidden input field would be located outside of the form.
Thanks for any advice!
It should be possible to render an Html.AntiForgeryToken() separately within each form. The runtime is designed with this scenario in mind. The first call to AntiForgeryToken() sets a flag saying "I've set the token, any other calls to me for this request should use the same token value."
Related
A form inside a turbo_frame is blocked from being submitted a second time.
Both the current page and the form action are the same path.
I see forms now have to redirect to a new location or return an error code: turbo/pull/39.
I have a form on every index view sending a GET request to the index action, which filters the records based on the url query parameters. This works great. Is this no longer possible with latest Rails? Is there a workaround that could be applied here, to avoid creating a new route for the form action?
These are idempotent filter/search requests, hence the GET method. A form is a handy way to collect and send the filter values. Is it correct/intentional that Rails with Hotwire insists on a redirect in this scenario?
Update:
It works if I submit the form as xhr instead of using Turbo. I add local: false and data-turbo: false to the form. Then add index.js.erb with document.getElementByID(<id of turbo frame>) and set its outerHTML to the rendered partial. Not sure if this will stop working due to deprecated ujs features (maybe mrujs can step in then).
what is the difference between Html.BeginForm() and Ajax.Beginform() in MVC3. I just want to know the scenarios where I can use Html.BeginForm() and where I can use Ajax.Beginform().
Ajax
Won't redirect the form even you do a RedirectAction().
Will perform save , update and any modification operations asynchronously.
Validate the Form using FormMethods - OnSubmit. So you are abort the Post
This creates a form that submits its values using an asynchronous ajax request. This allows a portion of the page to be update without requiring that the entire page be refreshed.
Html
Will redirect the form.
Will perform operations both Synchronously and Asynchronously (With some extra code and care).
Html.BeginForm will always use RouteTable to detrmine the action attribute value.
This will create a form on the page that submits its values to the server as a synchronous HTTP request, refreshing the entire page in the process.
Html.BeginForm() will create a form on the page that submits its values to the server as a synchronous HTTP request, refreshing the entire page in the process.
Ajax.BeginForm() creates a form that submits its values using an asynchronous ajax request. This allows a portion of the page to be update without requiring that the entire page be refreshed.
Html.BeginForm() will use simple posting on page, it means your page will be refreshed when you post your form.
when Ajax.BeginForm() will use ajax posting on page, it means your page will not be refreshed when you post your form.
#Html.BeginForm is used to post the data by full page refresh whereas #Ajax.BeginForm performs Post back function and allows some portion of Html to be reloaded rather than overall page refresh.
Is the JSF 2.0 View Scope "back button" safe? e.g. if I store a model in View Scope and go from page 1, page 2, page 3, to page 4, modifying the model object along the way (via input fields), and then hit the back button twice to go back to page 2 and make changes (taking me again to page 3), will the model in view scope have only changes that were made when page 2 was originally rendered or will it have later pages' changes?
Oracle ADF had/has something called "process scope" that handles this by tokenizing what is placed into session, so each page has its own copy of the model.
To start, the view scope is bound to a particular page/view. Multiple views won't share the same view scoped bean. The view scope starts with an initial GET request and stops when a POST action navigates with a non-null return value.
There are in general the following scenarios, depending on whether the browser is instructed to cache the page or not and the JSF state saving configuration. I'll assume that the navigation between those pages took place by a POST request (as it sounds much like the "Wizard" scenario).
When the back button is pressed:
If browser is instructed to save the page in cache, then browser will load the page from the cache. All previously entered input values will reappear from the browser cache (thus not from the view scoped bean in the server side!). The behavior when you perform a POST request on this page depends further on the javax.faces.STATE_SAVING_METHOD configuration setting:
If set to server (default), then a ViewExpiredException will occur, because the view state is trashed at the server side right after POST navigation from one to other page.
If set to client, then it will just work, because the entire view state is contained in a hidden input field of the form.
Or, if browser is instructed to not save the page in cache, then browser will display a browser-default "Page expired" error page. Only when the POST-redirect-GET pattern was applied for navigation, then the browser will send a brand new GET request on the same URL as the redirect URL. All previously entered input values will by default get cleared out (because the view scoped bean is recreated), but if the browser has "autocomplete" turned on (configureable at browser level), then it will possibly autofill the inputs. This is disableable by adding autocomplete="off" attribute to the input components. When you perform a POST request on this page, it will just work regardless of the JSF state saving method.
It's easier to perform the "Wizard" scenario on a single view which contains conditionally rendered steps and offer a back button on the wizard section itself.
See also:
javax.faces.application.ViewExpiredException: View could not be restored
What scope to use in JSF 2.0 for Wizard pattern?
I put the begin/end form statement in the layout page so that I don't have to repeat it on several pages. Below's a simplified version of the code.
#using(Html.BeginForm())
{
#RenderBody()
<input type = "submit" name = "nextButton" value = "Next-->" />
}
Things are working well. Unfortunately, I have a page that has several "Delete" buttons. I want to generate a form for each delete button so that it can send the id of the item to delete back to the controller.
Can I do that knowing that there's already another form on top of that?
Thanks for helping
As Mrchief says, the the HTML specs forbid nested forms. Since MVC just generates standard HTML, you have to work withinn the framework of the spec.
Why not just create two master layouts, and use the form based one most of the time, but use one without a form when you need more control over the embedded forms.
This is the why you should really only use forms exactly where they are needed, not just everywhere.
Do note that nesting of forms is not allowed as per the W3 specs
Every form must be enclosed within a FORM element. There can be
several forms in a single document, but the FORM element can't be
nested.
There is an interseting article about caveats of nesting forms here.
In this case, it is better to generate a form for each button instead of having a single form.
ASP.Net web forms restricted you from having multiple forms on the page by using runat=server attribute (and the framework ensuring that only one per page was allowed). MVC forms are pure HTML so you can have multiple of them.
Before starting, I do have a very particular question and if you want to answer it go straight to the end. But I do welcome comments and advices hence the lengthy post.
OK, we deal with a lot of forms and some of these forms are quite lengthy and have many fields. We also have a requirement - in addition to top level fields - to be able to have variable number of repating rows - as we call them. For example, let's think of a customer which has name, surname and age while it can have zero or many addresses (say 0 to 10) so the user must be able to add or remove contacts from the form while filling it in. So typically user gets and "Add" button to add more addresses and next to each address, a delete button. Potentially there could be more than one repeating section in the same form but I am not going there. The point is, because of legal and historical reasons, all the forms must be saved at once so while the forms can be edited, we cannot accept a half-filled form and have another page for users to add and remove addresses, e.g.
I am using ASP NET MVC 2 (strongly typed views with a single generic controller) with client side validation and heavy jquery scripting for flashy features. We are probably going to migrate to ASP NET MVC 3 very soon and I am already playing with 3 for finding a good solution. These addresses are defined on the Model as List<Address>, e.g.
I currently have a working solution for this issue but I am not satisfied with it: I have an HTML Helper that names the add or delete buttons and a bit of JavaScript to disable validation and allow the form to be posted back (even invalid) and since I can find out the name of the button that was clicked, I have all the necessary logic to handle add or delete and works really well.
But I am posting back and the form is reloaded and I am looking for an aletrnative solution. Here are what I can do:
Do everything in the client side. "Add" button will clone one of such addresses and "Delete" button will remove() the element. I only have to rename the indexes which I have done. We were using jquery calendar and it was breaking on the new elements which I have also fixed. But the validation is not working which can probably work with ASP NET MVC but this solution looks like a very brittle one - a house of card which looks great before you add another card.
Post the whole page usin Ajax and then load it back again: This is probably better than my current solution but only slightly.
Use ajax to post the form and get back JSON and use the data to build the elements or remove them: Again a house of card because of extensive client side scripting
Serialize the form and post using Ajax to a particular action and get back only the repating section (as a partial view). The action on the controller can be reused and called from the view itself to return the partial view
OK last one is the one I am working on but there is an issue. ASP NET MVC 3 with unobtrusive validation works only if the form is engulfed in a BeginForm() while my top level view has a BeginForm() but not my partial view. It works well when I call it from the view but not on the ajax call to get just the repeating section.
(Question)
So is there a way to tell ASP NET MVC 3 to spit out validation data atttributes regardless being in a BeginForm() block?? To be honest if this is not a bug, this is definitely an important feature request. I have in fact used reflector to disassemble the code and the condition seems to be there.
Short Answer:
Add this to the partial view:
if (ViewContext.FormContext == null)
{
ViewContext.FormContext = new FormContext();
}
I don't think it is possible using the default unobtrusive libraries supplied. If you look at jquery.validate.js and jquery.validate.unobtrusive.js it looks like it only validates what is inside the form.
There's a few posts about it if Googled and a few work arounds.
I had a similar issue (although much simpler) where I had a validation summary at the top of the page and multiple forms but the unobtrusive javascript would only populate the view summary if its inside the form (jquery.validate.unobtrusive.js line 39 if interested...).
I'm not sure if the validation library is extendible but most things in jquery are so that might be an option if you want to go down that road.
As far a possible solution to your problem I'll put in my 2 cents for whats its worth.
You could have two actions that are posted to. The first action is you post your model with no js validation and all validation is handled in the code - this will catch all user with javascript turned off.
Your second action is you serialized the model. In mvc 3 using the Ajax.BeginForm has an AjaxOption for Url where you can specify an action for the jquery to call (where it serializes the form form you and you can decorate your action with your strongly typed model). Here you can check the model and return a json result and handle this in the javascript.