JSF do post and redirect with params - jsf-2.2

I have been reading a few posts saying that you can do the following:
Assuming this entry in faces-config.xml
..
<from-view-id></from-view-id>
<navigation-case>
<from-outcome>home</from-outcome>
<to-view-id>/xxx/index.xhtml</to-view-id>
</navigation-case>
..
an this String in the action implementation:
return "home?param=1&faces-redirect=true";
This does not work for me. It gives me an error saying that it cannot match the navigation case:
Unable to find matching navigation case with from-view-id '/xxx/yyy.xhtml' for action 'home?faces-redirect=true&param=1' with outcome 'home?faces-redirect=true&param=1
On the other hand if I use the full view name it works just fine. Is this a bug or am I doing something wrong?

You're mixing implicit and explicit navigation.
With explicit navigation, your code is supposed to return an outcome only. Whether to redirect or not should be encoded in the XML rule, not in the outcome which you return from your bean.
But as far as I know, navigation rules have no real use anymore. Just delete them and return the view with the required parameters and redirect options and such from your bean. When you have more then 10 pages you'll be ready to pull your hair out when you use navigation rules. (Ironically, navigation rules were created to manage large amount of views, but exactly with a large amount of views they become completely and utterly unmanageable)

Related

How do I use continuations in FubuMVC

https://github.com/adymitruk/fubumvc/commit/083e1d593d4e797ac04fb493acd1e29a332cd303?w=1
It seems returning a continuation breaks the binding to the view. It used to work before I added the continuation. Now I get a blank page for the default view.
You're using the same input model for your get and your post, so when you transfer, you get into an endless loop. I'm surprised you don't get a stackoverflow. There must be some checking in FubuContinuation that breaks the loop.
You're using the input model as the view model which you (generally) shouldn't do.
Your form tag needs to be a
Also, it looks like due to the naming of your models and the folders, the default view conventions weren't matching up views to your actions. To get things working, I threw them all in the same folder (bad, I know).
You'll want to sort out the folders and namespaces before doing anything serious with this.
Here's the pull request which I was able to get working and posting and such:
https://github.com/adymitruk/fubumvc/pull/1

How to load the layout at runtime in Magento?

I know that we can design the layout in *.xml then in the action just invoke loadLayout, and renderLayout to render the blocks/views.
But, I have a question is:
- How can I load the layout at runtime?
If we have an action which does not really design its layout and will be decided how to render at runtime.
You can please consider the answer from the question for more clear.
Writing a new answer because it seems that you actually DO still want to render, you just want to render a different route's layout XML updates. I believe the _forward() method from Mage_Core_Controller_Varien_Action will allow you to do what you are describing with the least amount of pain.
You should add your action controller directory ahead of the catalog directory, create a ProductController with a viewAction, and check customer is not logged in - in this check you would call $this->_forward('customer','account','login');.
This approach though is going to require more effort in order to be usable, as I imagine that you want the user to be sent to the product page upon login. Have you seen Vinai Kopp's Login Only Catalog module? It should do this for you.
loadLayout() and renderLayout() just execute block output method toHtml() (usually) and take the resulting strings and apply them to the response object via appendBody(). In an action controller you can just call $this->getResponse()->setBody('response string'). How you build the string is up to you.
You can also use Mage_Core_Block_Flush to immediately send output to the browser without using the response object.

What is the canonical way to handle errors during Ajax-requests?

For normal requests we can simple register an <error-page> in web.xml. However, this does not apply to Ajax-requests. By default errors during an Ajax-request will result in a little pop-window in the browser that shows the exception.
The main example I am struggling with is handling a ViewExpiredException in a uniform way. For standard requests, I redirect to a page that explains that the user is not logged in and provides a link to the login-page. I would like to do the same for Ajax-requests. There seem to be several ways:
I could write a javascript function that handles the error on the client-side and redirects to the error-page. I would then have to add this function every <f:ajax>-tag on all pages using the onerror-attribute. Is there a way to tell JSF that I want to have this javascript-function as the default error-handler for all <f:ajax>-tags?
I could use a custom exception-handler, as described in this blog. This seems to do what I want, but I wonder if it is overkill. Is there no simpler solution?
So my question is, how is this supposed to be solved? Which of the approaches I listed should be used? Is there another approach that I do not know of?
You can use jsf.ajax.addOnError() to set the default error handler. E.g.
jsf.ajax.addOnError(function(data) {
alert(data.responseText);
});
See also chapter 13.3.6.2 of the JSF2 spec. You can find all properties of data object in table 14-4 of the JSF2 spec.

serving error pages in mvc: the control or the view?

Let's start by getting on the same page about MVC on the web. The control receives requests, selects a view, sends a response that it gets from the view. (Maybe the control gets data from the model, maybe the views do it themselves, I don't care.) Errors can occur, so we want to handle the errors and display a message or error page to the browser.
I'm trying to decide if these error messages/pages are part of the control or come from the view. Perhaps it is different for different kinds of errors.
some examples:
The request path is meaningless, so we want to respond with a custom "not found" page.
The control selects the "not found" view and uses its response
The control builds the "not found" page itself
.
The controller selects a view successfully, but the view throws an exception.
The view returns an error status. The controller checks the status and then selects a new view and uses its response
The view returns an error status. The controller build the error response itself.
The view handles the exception and returns a valid error page or message to the controller. The controller blindly sends it as the response.
Now, the difference between the first two options in both cases is technical/organizational, and there is probably no difference to the user. Is there a standard opinion on this (perhaps across MVC frameworks) or is the choice just arbitrary? What is the preferred method?
The controller selects a view successfully, but the view throws an exception.
If the MVC design pattern is followed, this should never happen. The only logic that should be contained in a view is solely display logic (formatting, localizing etc).
Errors should be trapped either at the model or controller level, but it's up to the controller to decide what to do with the user (redirect/404/etc).
Edit:
Of course it's not the only way.. I'm sure that you can find hacked up, bastardized code all over the place that does different things. As far as I'm concerned, yes - your views should be engineered in such a way that errors will not need to be trapped (other than ajax/javascript errors, but that's where they belong anyway).
I usually set it up so that I have a different view for each HTTP error code I want to handle, and a generic one for a catch-all. The controller will be responsible in this case to pass the error data to the view for rendering (usually as an array). Of course, this could also be done using an ErrorModel (which would be the 'correct' way of implementing it - I'm just lazy ;))
The approach I take is to allow the controller to handle your first case (route based errors). Any request made that is either unauthorized or poorly formed gets managed by a "static content" controller that renders the appropriate error view.
For your second class of errors - I'm not sure how/if the view can communicate back to the controller that it's thrown an error. I'm actually interested to see other's opinions, because as far as I know if a view encounters an error, it's up to the view to deal with it.

Getting the url of an aspx page using the page type

I'm using a web application project.
I have a folder in my web root called Users and in the folder I have a page called UserList.aspx
What I want to be able to do is type in Response.Redirect(Users.UserList.URL)
What I reckon I can probably do is create a class that extends Page and add a static property called URL that calls MethodInfo.GetCurrentMethod().ReflectedType (I think this works haven't tested) and then have that convert Users.UserList -> ~/Users/UserList.aspx
The problems with this method that I know of are one I need to go through every page and make it extend the base class and it doesn't work with any pages that contain a '-' character.
The advantages are that if pages are moved around then there aren't any broken links (Resharper gives out when there is a Page with the wrong namespace).
Also then every individual page that takes query string params could have a static method so that if I want to add/remove params I can see what uses those params etc.
Also if I want to call that page I don't have to check the name of the params e.g. UserId userId, Id or id. So that would look something like Users.ViewUser.GetUrl(1) -> ~/Users/ViewUser.aspx?UserId=1
So the question is: Is there a better way of doing this? Or is this a bad idea in principal?
You could just create an extension method for the base Page class that does what you are thinking. That would avoid having to go back and modify the base class for all your pages.
There is a better way. Create a traffic cop that knows about paths. Then if paths change, your data model changes or other stuff you just change that one place. Plus you could have read from a config file and make changes at run time.
Thus your call looks like this:
Repose.Redirect(TrafficCop["Users.UserList"].URL)
or some other way if you don't like the syntax.
The MethodInfo.GetCurrentMethod().ReflectedType doesn't work so I came up with another method of doing this using generics.
Instead of Users.ViewUser.GetUrl() or Users.ViewUser.URL it's GetUrl()
For a page with parameters it's still Users.ViewUser.GetUrl(1), it isn't ideal because they should both have the same way of being called but better than strings I guess.
Going to leave the question open for a while just in case.
edidt: I think I will actually just create another method called GetUrl(String getQuery) because if I have two parameters that are of the same type it doesn't work very well.
further edit: I found out how to do exactly what I want to do.
created a class called BasePage:Page where T : Page
on that are the static methods redirect and geturl
each page inherits from the base page as follows: MyPage:BasePage
Any page can redirect to that page by using the command MyPage.Redirect();

Resources