Refresh a Sitecore rendering after logon - asp.net-mvc

I feel like this should be obvious, but I'm stumped. We're running Sitecore 7.1 with MVC.
There is a Header rendering that includes conditional logic depending on the status of Sitecore.Context.IsLoggedIn. Works fine.
There is a second rendering that either allows the user to log in OR displays account information. When the [HttpGet] acton is called, the controller checks IsLoggedIn and returns one of two views. When the [HttpPost] action is called (i.e. when the user logs in), The controller calls AuthenticationManager.Login() and then returns the view with the account info. Works fine.
It's a simple solution that allows us to place one rendering on the page, and it works great, except for one thing: the header rendering still shows the not-logged-in content immediately after logging in.
Caching is turned off on the header rendering and in the presentation details. When any link is clicked or the page reloads, the header updates to show the correct info. The problem is only after the initial request/response, when the login form submits and returns an alternate view. Although we've had a complete HTTP request/response cycle, it's like Sitecore doesn't bother to check anything except the rendering that was directly affected.
I know I can solve this by returning a hard Redirect() after logging in but that seems inelegant and creates annoyances, like losing ViewBag info.
What I am really looking for is a way to tell Sitecore, "hey, refresh that other rendering!"
The fact that I can find nothing at all on-line about this 'problem' tells me I might be doing something conceptually wrong.

As I see it there are two ways of handling this problem:
FormHandler
You use #Html.FormHandler to specify a Controller and an Action to handle the authentication. The FormHandler action will execute very early (see: https://twitter.com/dmo_sc/status/480001473745399809) in the page execution, before anything is rendered, and all your Renderings will have the same view of whether users are logged in or not.
Martina did a good writeup on Sitecore MVC and forms:
https://mhwelander.net/2014/05/28/posting-forms-in-sitecore-mvc-part-1-view-renderings/
https://mhwelander.net/2014/05/30/posting-forms-in-sitecore-mvc-part-2-controller-renderings/
Post-Redirect-Get
I really want Sitecore MVC to have this feature build in, as it is useful for all form submission scenarios (bar AJAX). The idea is to handle the POST request and work out what you want to respond (and store this in tempdata). Instead of returning a ViewResult you issue a redirect to the same URL, this forces a GET to the page (at this point all the logged in state is same for all Renderings) where you fish the result out of tempdata. Also P-R-G protects against resubmitting POST requests.
cprakash documented his experience doing P-R-G:
https://cprakash.com/2015/01/12/sitecore-mvc-form-post-simplified/
Off Topic: Multiple forms on single page
This will not solve the OP problem, but worth having a look at in this context:
http://reinoudvandalen.nl/blog/ultimate-fix-for-multiple-forms-on-one-page-with-sitecore-mvc/

In MVC, your renderings are executed sequentially, top to bottom. So if your header rendering comes before the login status rendering, it's going to be done before the user is logged in.
The elegant way to do this would probably be to do your post and update both elements via JavaScript. If you want to keep the header logic separate from the login status logic, your login status script could allow other components to register their own callbacks. You could even build out a client-side message bus, if you will be doing this sort of thing frequently.

You could take a look at Jeremy's approach:
https://jermdavis.wordpress.com/2016/04/04/getting-mvc-components-to-communicate/
The key takeaway, I think, is where he switches the order of the placeholders by placing the results into variables and then render them wherever you want them.
#{
HtmlString main = Html.Sitecore().Placeholder("MAIN");
HtmlString head = Html.Sitecore().Placeholder("HEAD");
}
<head>
#head
</head>
<body>
#main
</body>

Related

ASP.NET MVC 4.0 Chrome Caching

I have code in place to disable caching in my MVC application. I'm using the following response headers. They seem to work in all browsers except for Chrome (currently using version 31.0.1650.48). Users are able to submit a form with model values. When they hit the back button I need the page to reload with a blank model. The headers appear to partially work since the request is hitting the action and returning the blank model. However the view isn't updating. The values from the previous post are being retained. I've tried clearing the ModelState but that doesn't work. Any suggestions? Thanks in advance!!
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1))
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(False)
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches)
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache)
filterContext.HttpContext.Response.Cache.SetNoStore()
Turning off autocomplete for the form fixed this for me. I appreciate all the input!
<form autocomplete="off"></form>
There is a way to do this in javascript for everything in one go like so...
document.getElementById("YourFormID").reset();
Just add an id to your form and all your inputs will reset on page load. Regardless if its a first time visit or a back button click with the page being cached. The biggest difference from your solution and this is that "the autocomplete attribute is new in HTML5". Which means it is not supported in older browsers, and though it does what you want it also prevents the user from autofilling fields. Meaning that for example on text types inputs users will not see a suggestion of words they may have entered on previous or other pages. You can see an example here.

Callback in Rails after view render (for logging purposes)

Short version: Is there a callback when the rails view is finished rendering?
Longer explanation of my actual problem:
I have this issue where I want to generate a history-object because of some APIs I'm using. So I will be appending to this history object possibly several times before saving it. I know that I can safely save it when the view is rendered, because then there will not be any more calls to the APIs.
After quite a while of googling I can still not find any way of doing this. Is my intended approach the right one, to get a callback from the renderer that says "now everything is rendered. Go ahead and save", or should I do it in a different way?
Does such a callback even exist, or do I need to make it myself?
I would lean towards suggesting that you shouldn't be leaving functionality until after the page has rendered - you should really have completed any API calls in the controller before you start outputting the page. However, if you really must do this you can use javascript to fire off a function (such as an ajax request to an action) after a page has finished rendering.
http://api.jquery.com/ready/ should give you a good starting point!

Best practice/design for a multi-page form in .NET MVC3

I am working on a web application that involves the user filling out a multi-step form that spans several pages. The form has tabbed navigation across the top (these links do not submit the current page) and a next button at the bottom (which does submit). I am considering several strategies for handling form submission/validation:
one action method and view per form page. When you hit next, it submits the form to the action method for the next page. If there are validation errors, you are redirected back to the previous page:
URL's are descriptive and can be copy-pasted
Only redirects in the error case
Since the redirect does not have the form data, we lose context about the submission which makes it hard to display certain error messages
The same validation logic works for redirecting the user if they try to visit a step in the flow that they aren't ready for yet
one action method and view per form page. When you hit next, it submits the form to the current page action. If there are validation errors, the same view is returned. Otherwise, we redirect to the next page action:
URL's are descriptive and can be copy-pasted
Redirects are very common (not sure if this is bad)
When displaying validation errors, we are in the same request as the form submission so we have full access to the invalid input
Have to pass additional context if we want the ability to, for example, add a "Previous" button which also submits
one action method for ALL pages. URL's contain additional context about the step being submitted (e.g. MyController/MyAction/{step}). The controller message selects which view page to return depending on validation and the current step.
URL's are not descriptive (e. g. if I submit step 1 to go to step 2, then the URL the user sees will be the same regardless of whether page 1 (invalid) or page 2 is returned
No redirects
When displaying validation errors, we are in the same request as the form submission so we have full access to the invalid input
A different method I haven't listed here
I have tried to enumerate what I see as some of the pros and cons of each method, but I would be interested to know:
What are other pros and cons of these methods? Are mine correct? Could some of the cons I've listed be designed around?
Is there a standard approach to this problem which I should be using? If so, why is it the standard approach?
I would highly recommend option 2 with a minor modification. You may want to think about also creating one view model per action/view as well. If you have one model that spans all the pages, validation will occur across ALL properties, meaning that even though the user can only edit part of the model on each screen, they could get validation warnings for properties they can't see. We did this recently in a project and it worked beautifully. You have to do some data manipulation in the back-end to combine everything back together, but it was worth it in the end.
As you said, your URLs would be deep-linkable, which means users can Copy/Paste, and more importantly, they can add the page as a favorite in their browser, allowing them to come back to the same place very easily. In my opinion this makes option 3 obsolete.
You will also benefit from the fact that all of your logic for navigation is occurring in one place. You'll have to store the state of the "wizard" on the client (which page you're currently on) so that your controller knows what to do on submit. You'll want to analyze the state of the wizard and make a decision for where the user needs to go next. If you go with option 1, you won't know where you "came from" and server-validation errors will be difficult to display to the client. This is a beautiful example of the POST - REDIRECT - GET pattern. Each page would have 2 actions, a GET that takes simple ids, and a POST which takes more complex models. Post the server, figure out where to go next, redirect to a GET.
Lastly, consider your previous button simply linking directly to the previous step, instead of submitting the form. Otherwise, the user could potentially get stuck on an invalid step. This happened to us and again, worked very nicely.
Hopefully this was helpful. Good luck!

Grails: Rendering two Views simultaneously with one Controller Action

One action of one of my controllers needs to generate(redirect/render) two separate views simultaneously and show both the pages to the client. It will be like when the user submits his info, the page will redirect to a new page with a list. At the same time another page needs to pop up in a new window containing some additional info (user would print this page). I know, I can resolve the issue with a single page, but I was wondering whether there is any ways to produce two separate pages/windows simultaneously from a single controller action.
Thanks in anticipation
The simple answer is NO. Grails isn't doing anything magical. It's still constrained to normal HTTP request/response lifecycle. A single request gets a single response. What you're asking for sounds like you want grails to be able to generate 2 responses for a single HTTP request which is impossible. The response is either a page for the browser to render or it's a redirect message for the browser to go to another URL.
You could write your action that it can handle normal and ajax requests. See the docs here:
Responding to both Ajax and non-Ajax requests
Then you could generate your "normal" view. After that you call the same action by using ajax on the client side and load the data for your pop up page.
why not use a <script>window.open()</script> in your main view in order to open the popup?

What is a postback?

I'm making my way into web development and have seen the word postback thrown around. Coming from a non-web based background, what does a new web developer have to know about postbacks? (i.e. what are they and when do they arise?)
Any more information you'd like to share to help a newbie in the web world be aware of postbacks would be most greatly appreciated.
The following is aimed at beginners to ASP.Net...
When does it happen?
A postback originates from the client browser. Usually one of the controls on the page will be manipulated by the user (a button clicked or dropdown changed, etc), and this control will initiate a postback. The state of this control, plus all other controls on the page,(known as the View State) is Posted Back to the web server.
What happens?
Most commonly the postback causes the web server to create an instance of the code behind class of the page that initiated the postback. This page object is then executed within the normal page lifecycle with a slight difference (see below). If you do not redirect the user specifically to another page somewhere during the page lifecycle, the final result of the postback will be the same page displayed to the user again, and then another postback could happen, and so on.
Why does it happen?
The web application is running on the web server. In order to process the user’s response, cause the application state to change, or move to a different page, you need to get some code to execute on the web server. The only way to achieve this is to collect up all the information that the user is currently working on and send it all back to the server.
Some things for a beginner to note are...
The state of the controls on the posting back page are available within the context. This will allow you to manipulate the page controls or redirect to another page based on the information there.
Controls on a web form have events, and therefore event handlers, just like any other controls. The initialisation part of the page lifecycle will execute before the event handler of the control that caused the post back. Therefore the code in the page’s Init and Load event handler will execute before the code in the event handler for the button that the user clicked.
The value of the “Page.IsPostBack” property will be set to “true” when the page is executing after a postback, and “false” otherwise.
Technologies like Ajax and MVC have changed the way postbacks work.
From wikipedia:
A Postback is an action taken by an
interactive webpage, when the entire
page and its contents are sent to the
server for processing some information
and then, the server posts the same
page back to the browser.
Expanding on the definitions given, the most important thing you need to know as a web-developer is that NO STATE IS SAVED between postbacks. There are ways to retain state, such as the Session or Viewstate collections in ASP.NET, but as a rule of thumb write your programs where you can recreate your state on every postback.
This is probably the biggest difference between desktop and web-based application programming, and took me months to learn to the point where I was instinctively writing this way.
Postback happens when a webpage posts its data back to the same script/dll/whatever that generated the page in the first place.
Example in C# (asp.net)
...
if (!IsPostback)
// generate form
else
process submitted data;
Web developement generally involves html pages that hold forms (<form> tags). Forms post to URLs. You can set a given form to post to any url you want to. A postback is when a form posts back to it's own page/url.
The term has special significance for ASP.Net WebForms developers, because it is the primary mechanism driving a lot of the behavior for a page — specifically 'event handling'. ASP.Net WebForms pages have exactly one server form which nearly always posts back to itself, and these postbacks trigger execution on the server of something called the Page Lifecycle.
The term is also used in web application development when interacting with 3rd party web-service APIs
Many APIs require both an interactive and non-interactive integration. Typically the interactive part is done using redirects (site 1 redirects a user to site 2, where they sign in, and are redirected back). The non-interactive part is done using a 'postback', or an HTTP POST from site 2's servers to site 1's servers.
When a script generates an html form and that form's action http POSTs back to the same form.
Postback is essentially when a form is submitted to the same page or script (.php .asp etc) as you are currently on to proccesses the data rather than sending you to a new page.
An example could be a page on a forum (viewpage.php), where you submit a comment and it is submitted to the same page (viewpage.php) and you would then see it with the new content added.
See: http://en.wikipedia.org/wiki/Postback
Postback refers to HTML forms. An HTML form has 2 methods: GET and POST. These methods determine how data is sent from the client via the form, to the server. A Postback is the action of POSTing back to the submitting page. In essence, it forms a complete circuit from the client, to the server, and back again.
A post back is anything that cause the page from the client's web browser to be pushed back to the server.
There's alot of info out there, search google for postbacks.
Most of the time, any ASP control will cause a post back (button/link click) but some don't unless you tell them to (checkbox/combobox)
Yet the question is answered accurately above, but just want to share my knowledge .
Postback is basically a property that we can use while doing some tasks that need us to manage the state of the page, that is either we have fired some event for e.g. a button click or if we have refreshed our page.
When our page loads for the very first time , that is if we have refreshed our page, at that time postback-property is false, and after that it becomes true.
if(!ispostback)
{
// do some task here
}
else
{
//do another task here
}
http://happycodng.blogspot.in/2013/09/concept-of-postback-in.html

Resources