Grails - Redirecting a Request - grails

Can't I just call then function "second" with no redirect action if I in the same class to get the same result i would get with redirect action in the following code?
class SampleController {
def first() {
// redirect to the "second" action...
redirect action: "second"
}
def second() {
// ...
} }

Can't I just call then function "second" with no redirect action if I
in the same class to get the same result i would get with redirect
action in the following code?
Of course you can call a method from within a controller action but whether or not you get the same result depends on a number of factors. The best way to approach this is to understand the differences between a redirect, a forward and invoking a method. Understanding those will help you understand when each of them makes sense.
When you initiate a redirect the response is sent back to the client with information which causes the client to send a separate request back to your application. A full HTTP round trip is made. A forward is similar to a redirect except it all happens within the first request. Control is sent to the forwarded action without needing to go back to the client and having it send a second request. Invoking a method is different than all of that. Invoking a method is just invoking a method and there are a number of things that won't happen when you do that. For example, filters (Grails filters or regular servlet filters) will not be involved in that method call, even if the method you are calling is a controller action and there are filters configured that would normally apply to calls to that action. You really should never invoke a controller action method directly. If the method includes helper code that you might want to call, put that code in a regular non-action method (make it non-public) and then invoke it from wherever that makes sense. Usually a better idea is to move that method out of the controller altogether and put it in a helper class where it will have a number of a benefits including that it can be re-used wherever appropriate, tested separate from a controller, etc. This helper class might or might not be a Grails service, depending on how it is used and what it is doing.
I hope that helps.

You can use
forward action: "second"
Forwards a request without issuing an HTTP redirect.

Related

What is the right way to detect if a request is a "forward()" from another controller action?

I have a couple of "before" type filters, which I would like to trigger only when a real, non-forwarded request arrives at my server. And not, when I sometimes am forwarding a request to another controller/action for further processing.
My questions if if there is a simple way to detect this particular kind of requests caused by a "forward()" call?
Alternatively, I am considering to parse the request url and check if controller and action match with the current controller/action, but I am not sure if this will work - and it sure is quite an ugly way to handle this issue...
From within my controller action I have tried to see if there were any useful attributes for this purpose on the request object, but could not find any, except from "javax.servlet.forward.request_uri" and "org.codehaus.groovy.grails.CONTROLLER_NAME_ATTRIBUTE" +"org.codehaus.groovy.grails.ACTION_NAME_ATTRIBUTE".
However, it seems like comparing these values with each other will not work if the request uri originates from a UrlMapping,(in which case it might not match with the controller/action)
You can determine if a request was forwarded by looking up the servlet attribute org.grails.FORWARD_CALLED:
request.getAttribute('org.grails.FORWARD_CALLED')
Minimal example (in Grails 3.3.9, though same attribute in 2.5.x):
def index() {
forward action: 'fwd'
}
def fwd() {
if (request.getAttribute('org.grails.FORWARD_CALLED')) {
render 'was called by forward'
} else {
render 'called directly'
}
}
Calling the endpoints:
$ curl localhost:8080/foo/index
was called by forward
$ curl localhost:8080/foo/fwd
called directly

How to call a function *only once* in ASP.NET MVC page cycle

I have an ASP.NET MVC web app and have a function that I need to call when the page loads only once. Right now I have the function being called from a base controller OnActionExecuted.
The issue I'm having is that this function is called multiple times - once for the page, and then multiple times for different ajax calls that I have on the page. I've tried putting the function on Controller Initialize but this is also called for each ajax call to a controller action. So is there some function in the ASP.NET MVC page cycle that only gets called when a page is requested (GET) and not for all of the ajax calls (POST)? The only thing I can think of is putting all of the ajax calls in separate controllers that don't inherit from the base controller but there must be a nicer solution.
Depending on how you're doing your AjaxRequests you could use something like the following:
public ActionResult Index()
{
if (!Request.IsAjaxRequest())
{
LoadConfiguration();
}
// Rest of Action method (snip)...
}
This works if, for instance, you're performing Ajax with the jQuery JavaScript library which sends a special token to the server to indicate that it's an Ajax call (I'm sure other libraries do this). This might be better just in case someone changes the JavaScript code to perform GET Ajax requests.
One thing you mentioned does intrigue me though "The issue I'm having is that this function is called multiple times" - actually 'technically' this is not true. It IS only getting called once....per request, all those Ajax calls are treated as separate requests by the server, as if the user is requesting a page via the web browser. It sounds like what you really need is a way to differentiate between web page HTTP Requests, and Ajax HTTP Requests, hence the above solution.
It came to me right after posting the question...
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
if (Request.HttpMethod == "GET")
{
LoadConfiguration();
}
}
You can either do this work in the application scope (on start, in global.asax or other similar approaches), or store a configuration object in the session (or a flag to identify it has already been done, if there is nothing to store).

What's the Rails way to temporary branch to a different controller's action?

In my Rails controller I want to branch to a different controller's action, show its view and then return back to my original action, i.e. it's not a simple redirect, more like a sub-procedure call.
I want to use this whenever a user does something suspicious, like editing a post too often in a row. I still want to allow the edit, but first the user has to answer some CAPTCHA-like questions on a different page. (Similar to Authlogic-oid, where during validation the user is redirected to the OpenID provider's page)
You can push the current request into the Session, then do a redirect to the captcha, then have the captcha action look into the Session to check where it should redirect to.
IIRC, Autlogic does exactly that with redirect_back_or_default.
You can't.
Convert the common stuff into a helper method and then both the controllers should call this method.
It's possible to create an instance of the other controller and call methods on it, but you should probably reevaluate your organization first (look into helpers, modules, etc.)
#my_other_controller = MyOtherController.new
#my_other_controller.some_method(params[:id])

How to simiulate a JSON call from an HTTP GET Call?

At this moment I am calling my index view in one of two ways. Using the normal http view and serializing it JSON. In order to test it I am using the code below, and it works. I want to get it with a http get call. Like (http://localhost/article,json or something similar. Any ideas.
$.getJSON("/Article", function(json) {
$.each(json, function(i, article) {
alert(article.title);
});
});
At this moment the index called to /article is being differentiated with the following IsAjaxRequest method. but my real question is if I am able to get around the .getJSON method in JQuery to test the following code.
if (Request.IsAjaxRequest()) {
return Json(articles);
} else {
return View(articles);
}
If you are trying to reuse the same action method for both a full GET (the page load) and an AJAX call (via getJSON), you'll run into issues because each action method should have a unique name. Otherwise, the MVC engine can't tell which action method should be called when a particular Url is requested.
You'll need two separate actions: one for the full page load that returns a ViewResult and the other for the AJAX call that returns a JsonResult. If you need the Urls for these actions to look the same, you can also play around with mapped routes that direct to different action methods.
So, how about:
/Article/Index
Maps to the default Index action (full page load)
/Article/Refresh
Maps to the Refresh action (asynchronous JSON call)
I'm not sure I understand the question correctly, but can't you make an optional parameter called "format", so that you pass in ?format=json to switch what reply type you get back?
if(Request.IsAjaxRequest() || (!string.IsNullOrEmpty(format) && format.Equals("json"))
{
...
}
If you're wondering how to test your action and you're talking about doing automated testing, see if this post answers your question.

Would you ever want an action method to not return an ActionResult?

In ASP.NET MVC the convention is that a controller action method should return an ActionResult (or a type derived from ActionResult).
However, you can write a public method that returns pretty much anything and if that method is called (from a browser) the framework will package the return value up as a ContentResult and the browser receives a page of plain text.
This is all very interesting - but would you ever want to do this?
When you want to render something directly from your controller? e.g. using Response.Write(...); (or using other Response methods).
Not returning anything from an action method is essentially not responding to the client's HTTP request with a response.
An empty request might make sense in some cases (HTTP status being enough of a reply), but all web application patterns return something more than this (including, if I understand it correctly, REST: the new state of the entity).

Resources