How do I edit a HTML element from a controller? - asp.net-mvc

I'm trying to make it so when I click on a button, a method is called and some text on the page is updated. (The button runs some methods and updates a Semantic UI progress bar with how many methods it's done.)
How would I do this?
I'm using Razor, ASP.NET Core MVC, and ASP.NET Core 5.

Basically it's not a good idea to interact with UI elements in the controller. Doing that you ruin the whole idea behind the MVC pattern a part of which is the Controller.(The controller should know nothing of the view.)
Moreover each execution of a method in the controller represents executing a synchronous request to the server which results in refreshing the page in your browser. Imagine the page refreshes every time the progress bar needs to update. I guess you don't want this behavior. For updating a status bar in the way I think you want it you need to have asynchronous calls of those methods in your view.
If you have to change the UI depending on methods execution status I would suggest using AJAX to make async calls to your methods in the controller and when a response from a finished method comes you update the progress bar.
Hope now you have a better overview. Cheers!

So a possible solution would be:
Click listener in JS , which will send AJAX request to the controller. The controller function should return Non-relational data(preferably JSON). This data that was returned should be catched in the AJAX success function and in this success function you define you HTML change.

Related

Refresh a Sitecore rendering after logon

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>

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!

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?

MVC design pattern - who loads view initially

This query is about MVC design pattern in general and not ASP.net MVC framework
I understand in MVC (desktop application):
User clicks something in view
this is passed on to controller to manage
controller makes some changes in Model
Model calls method on view which has the logic to refresh UI
Questions around these:
Q1) Can controller also modify View or Model only updates View?
Q2) When screen loads for the first time, there is no Model change. Then, who fetches data from model and populates view? View directly calls Model and populates itself OR controller gets data and passes to view method OR some dummy event is raised at Model which updates View?
From model-view-controller :
The user interacts with the user interface in some way. (for example, presses a mouse button).
The controller handles the input event from the user interface, often via a registered handler or callback and converts the event into appropriate user action, understandable for the model.
The controller notifies the model of the user action, possibly resulting in a change in the model's state. (For example, the controller updates the user's shopping cart.)
A view queries the model in order to generate an appropriate user interface (for example, the view lists the shopping cart's contents). The view gets its own data from the model. In some implementations, the controller may issue a general instruction to the view to render itself. In others, the view is automatically notified by the model of changes in state (Observer) that require a screen update.
The user interface waits for further user interactions, which restarts the control flow cycle.
In the web context, you always have a request from a web browser. So the logic works as described above but there is a wrapper around it:
Browser sends request to server and waits for reply
The four steps above. In this case, the UI is also an internal model in the server.
The render engine creates a new UI (a new HTML page) from the internal UI model
The server sends the new HTML document back to the browser
Browser renders result

How to persist a model across multiple requests in ASP.NET MVC 2

I'm building a web application that has a particular model representing some events. Users need to be able to add N number of people to a given event. Choosing people is handled by a partial view.
I'm trying to build a menu that displays when users click "add a person" to the event. Because the event hasn't been filled out completely yet, there is nothing in the database to persist between requests.
I also have validation logic on the event page.
My proposed solution is to add the form to search or add for people on the event form itself and have a submit button that sends the values that have been added back to the server, where I can store them in ViewData or Session.
Unfortunately, doing this flags the validation.
My second solution is to load a partial view responsible for loading the UI to add/search for a person. I could add a little code on the method in the controller that returns a partial view storing the existing data in a session variable or viewdata. Trouble is, I have to submit the form to do it--again tripping the validation!!!
I'm wondering if perhaps I chose the wrong tool to do this...because in webforms, there would probably be a postback and you would just perform an operation on that postback. I'd like to avoid rewriting the application in webforms and am wondering if there are ways I'm overlooking in ASP.NET MVC.
Thanks in advance for the ideas!
I would probably have the partial view send it's data to the main page (with javascript). That way there is only one post to the server and it is when all of the data the user needs to enter has been filled out. How are you displaying the partial view? Is it on the main page (in a div), or is it a separate pop-up window? Either way, you should be able to use javascript to store this data on the main page and post all of the data back at one time.
HTH

Resources