How should asp.net custom errors work? - asp.net-mvc-2

I have implemented custom errors in my asp.net mvc application by following this article. What I have noticed is that if I go to http://www.mysite.com/some-non-existent-controller-and-action I get my 404 error page as expected. However, looking at what happens with firebug, I see that I get a 302 Found response for the non-existent page, which then redirects to my custom error page which then returns with a 404 (and displays the custom error page). Is this right? I don't think the 302 that is first returned is very good especially from an SEO perspective, and that maybe I need to think again about how I have implemented this.

The best guide(i think) for handling 404s can be found in this answer. Basically there are multiple ways in which 404s can happen:
No route exists - matched by the catch all rule.
Matched route but not found a controller - for rules with dynamic controller names - {controller}/{action}/{parameter} rule.
Found route, but didn't find action - handled through HandleUnknownAction override.
Found route and action but couldn't convert parameters - matched by the catch all rule.
The linked answer basically sets up a controller that can be executed from any point in the code without rewriting the URL - which is what you want.
In addition, you should also think about handling unhandled exceptions and bad URLs (like the ones containing unsafe characters like angle brackets). I that particular case you have to rewrite the URL, otherwise you can't render the response at all. These particular requests are kind of tricky, i blogged about that here.

Did you follow the advice down towards the bottom of the page adding a "catch-all" route that maps to your "NotFound" action:
routes.MapRoute("Catch All", "{*path}",
new { controller = "Error", action = "NotFound" });
If you make this the very last route you add, any "unknown" URLs will map directly to your "NotFound" action on the ErrorController and you can just return the "not found" view directly from there, no redirects required.

Related

Play Framework: Don't change URL after form validation failed

In a plain Play application I have the following scenario.
A route file which looks like this:
GET /accounts/add controllers.Accounts.add()
POST /accounts controllers.Accounts.create()
The first route results in a view where I can add a new account. The form to submit the new account looks something like this:
#helper.form(action = routes.Accounts.create()) {...}
Now the controller binds the input to the form and checks for any validation errors:
public static Result create() {
Form<Account> form = Form.form(Account.class).bindFromRequest();
if (form.hasErrors()) {
return badRequest(views.html.account.add.render(form));
}
...
}
Now the thing is, the client will see the same view with some additional error messages. However, meanwhile the URL has changed from http://example.com/accounts/add to http://example.com/accounts.
If the client now reloads the browser this calls GET http://example.com/accounts (which isn't even mapped in this scenario - thus getting a 404 - Not Found).
Maybe it's just me but I find this kind of annoying and browsing some GitHub projects I couldn't find a good solution for this case.
Of cause things would be much simpler if the second route is rewritten to:
POST /accounts/add controllers.Accounts.create()
... in which case everything works fine. But from a REST point of view this doesn't feel good either. The same applies to update scenarios (having GET /accounts/:id/update vs. PUT /accounts/:id).
Is there a guide on how to handle this? Am I getting something wrong or is this no problem at all (from a pragmatic point of view)?
It's not possible to leave the previous URL because a request for a new address has already been made. A controller only provides response for a requested resource. To go to the previous URL you could only make a redirect in case of validation failure but you would lost errors that way so this is not a solution.
I suggest mapping both actions with the same URL. This way you would solve problem with the browser reload.
If you create a REST service for http clients that aren't browsers you will probably want to serve different response than a simple http page. The separation of actions for particular clients could be a good solution for keeping REST API clean and a browser user happy.

Drupal 7 some non-existing URLs are not Redirecting to 404?

In Drupal 7, some of (non-existing) URLs are not redirecting to 404 or any error page it should. Instead, it still remains showing its Top Parent Folder. For example like:
www.mywebsite.com/items/aaaaaaaaaaaaa
www.mywebsite.com/items/bbbbbbbbbbbbbbbbbb
Every WRONG URLs under /items/ i put like above, are showing the Page of its parent:
www.mywebsite.com/items instead of get redirected to 404
I don't want its parent to be shown if there is no page really.
But the strange thing is, it is NOT happening on every patterns. I mean, another different parents like:
www.mywebsite.com/users/aaaaaaaaaaaaa
www.mywebsite.com/users/bbbbbbbbbbbbbbbbb
For the wrong url typed-in under this /users/ parent path, it is CORRECTLY redirecting to the 404 page.
What is it please?
If I understand your question correctly, it's not a problem at all.
That's because how your/contributed/core modules hooks Drupal menu system.
If a menu item (menu router item to be specific. Think about a path like "admin/config/development/performance") has no "%" sign in it, menu callback function will be executed.
For an example, if a module registers "items" path example.com/items path would not be a 404, and the appropriate menu callback function of the menu item will be fired. That callback function can make use of further URL parts (example.com/items/123) if given.
'node' is a good example. (technically they are different menu router items though) .
Opening example.com/node will not fire a 404.
If a module registers 'items/%' , then, example.com/items will fire a 404. In other words, the second URL part is required in order to execute the menu callback function.
If the problem you are facing is related to a custom module, make sure you register the correct version of your router items. If the second URL part is required, register items/%.
You can execute a 404 by calling drupal_not_found().
Look at this, really helpfull
http://peterpetrik.com/blog/2009/11/non-existent-urls-views-2
Are you using Views for that path (/items)?
Here is an issue for Views: Prevent duplicate content (because Views returns 200 instead of 400 404)
You could create a Contextual filter to prevent this.
merlinofchaos wrote:
If you don't want this behavior, add the Global: NULL argument to Views and use the setting to validate that the argument is empty.
For Drupal 6, the module Views 404 might help.
You can configure your drupal installation to redirect to a specefic 404 page that you create..
Go to www.yoursite.com/admin/config/system/site-information and enter your 404 page .

404 when post submitted; found when directly called

I have a ColdFusion enabled form (for validation) submitting to a separate page. When this form is submitted it is showing me a 404 on the action page, yet when I directly load the action url into the address bar it shows up (errors appear, but that's ok). This is by far one of the most odd issues I have encountered.
Form page: http://www.jefferson.edu/population_health/_archive/contact_me.cfm
Action page: http://www.jefferson.edu/population_health/_archive/contact_action.cfm
Even if I try passing the form variables via URL it gives me a 404.
My gut is that there is another service on that machine that is trying to take over the request whenever you submit data and binding it to another webserver...which, of course, it can't find the right page based on it's own webroot.
If you click http://www.jefferson.edu/population_health/_archive/contact_me.cfm, it loads fine and returns 200 header with IIS as the server, but if you click http://www.jefferson.edu/population_health/_archive/contact_me2.cfm it throws a 404, as expected, but it's properly handled with a custom 404 and the header response is still IIS. But if you click http://www.jefferson.edu/population_health/_archive/contact_me.cfm?foo=bar, it returns an ApacheSling default 404 and header information saying the server is "Day-Servlet-Engine/4.1.12".
Your page is posting to the page contact_action.cfm ... in your question you indicate that the proper page should be "mailaction.cfm".
If the action page is actually mailaction.cfm then you simply need to change the action attribute of your cfform.

Zend framework - duplication in translated url

I have these URLs
cz/kontroler/akce
en/controller/action
Is used transatable route and works it like charm. But problem is, that when you will write
cz/controller/akce
it works as well.
In generally when you have
cz/something-in-czech
en/something-in-english
which route to someController, will be works still
cz/some
en/some
because it is really name of controller.
How solve this duplicity content issue?
You can create a plugin that uses a preDispatch method. Before the request is executed, you can analyze the url requested and check if the requested language match the language of the params in the url (I mean controller and action). If not, you can redirect the user to the url that is in accord to the given language (basically you'll translate the controller and the action and then redirect the user to the right url).

An explanation of the Zend Redirector Action Helper

Is there a comprehensive explanation of how the Zend Redirector Action Helper works? I've read the reference guide, but am still not 100% clear. For example:
Apparently the goToSimple() is more like a forward(), than a redirect. Does this mean that it won't send a redirect message back to the browser?
If I want to send a redirect message back to the browser, which Redirector method should I be using?
Is there a way to get the forward() type of behaviour, without re-executing the init() method of Action Helpers?
This problem cropped up when I was implementing an ACL. I have an ACL Action Helper and its init() method adds the role 'current'. When I use the redirector's goToSimple() I get an error saying that the role is already registered. I can use if (!$acl->hasRole('current')) however I think it would be preferable not to be re-executing the helper's init() in the first place.
Not too comprehensive just a few quick notes about the redirector.
The redirector does a little bit more than a regular PHP redirect which you would use with header('Location: www.domain.com/new/location') in your script--following by an exit().
If you look at Zend_Controller_Action_Helper_Redirector it ultimately does exactly the same; if $_exit==true (default) everything leads to redirectAndExit() which calls header() and ends with an exit() call. However it terminates the framework properly, mainly the session if any.
The redirector does not forward internally it sends a default 302 code back unless you have set another code with setCode().
Methods gotoRoute() and gotoSimple() assemble the destination URL for you and call redirectAndExit() but only if $_exit==true. Or you can use their brethren gotoRouteAndExit() and gotoSimpleAndExit() which will exit immediately. The gotoSimple methods pass on to setGotoSimple which uses some methods to assemble the URL for you.
In your case I can only assume that the setGotoSimple method and one of the methods in it call the destination controller and fire up the init() method; however, only for checking but not forwarding.