ZF1 is calling unexpected controller - zend-framework

I have controller named
AbcController
, which is in default module. So it's normally called like
somedomain.com/abc
..and everything is dispatched correctly, however in case uf URL
somedomain.com/!abc
OR
somedomain.com/#abc
iƧ's still routed to
AbcController
, question is why ? Or better question is, where exactly is the url param transformed to controller name ? I'm trying to find that few hours by debugger.
Expected behavior: controller not found exception
Current behavior: view !abc/inde.phtml not found
This is completely strange, please point me. Thank you.
Update:
So, after more time I found the reason, why any characters such ! and # are trimmed:
Zend_Controller_Dispatcher_Abstract::_formatName()
function is doing following:
$segment = preg_replace('/[^a-z0-9 ]/', '', $segment);
Question is, how to skip that and to get correct state (not existing controller)

OK, so there isn't clear solution, or at least I didn't find any. Actually I have workaround - using static router to some other action, like "ind" instead of "index". In case of bad character, controller will be matched, but default action not, what will result in requested 404 response.
Issue is in ZF1 itself, as controller names are claned, but action names aren't. Shoulld be both or nothing, I think.

Related

How to redirect category page to first child in Umbraco without a ThreadAbortException

(I'm about to answer this question as well, because I've found the solution, but Google didn't really help, so hopefully this will gain some PageRank for the search terms I was using.)
We have a big Umbraco site with several sections, but most locales don't have section homepages. So if the structure looks like:
- Homepage
- Section1
- Page1-1
- Page1-2
- Section2
- Page2-1
- Page2-2
and so on, then going to ~/section1/ would redirect you to ~/section1/page1-1/ (and, likewise ~/section2/ redirects you to ~/section2/page2-1/).
At the moment, we use a macro that checks a property in the locale homepage and then redirects:
var node = Model.AncestorOrSelf("SiteHome");
var useCSSV2 = node.GetProperty("useCSSV2").Value;
if (useCSSV2 == "1")
{
Response.Redirect(Model.Children.First().Url);
}
We're seeing a bunch of occasions where macros don't load properly, with errors like
Error loading MacroEngine script (file: PrimaryNavigationSwitcher.cshtml)
displaying instead. Looking at the UmbracoTraceLog, I can see things like:
2014-11-25 00:11:28,226 [5] WARN umbraco.macro - [Thread 39] Error loading MacroEngine script (file: PrimaryNavigationSwitcher.cshtml, Type: ''. Exception: System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.AbortInternal()
at System.Threading.Thread.Abort(Object stateInfo)
at System.Web.HttpResponse.AbortCurrentThread()
at System.Web.HttpResponseWrapper.Redirect(String url)
at ASP._Page_macroScripts_SecondLevelPageRedirection_cshtml.Execute() in d:\webroot\www.mysite.com\macroScripts\SecondLevelPageRedirection.cshtml:line 8
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.WebPages.WebPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at umbraco.MacroEngines.RazorMacroEngine.ExecuteRazor(MacroModel macro, INode currentPage)
at umbraco.MacroEngines.RazorMacroEngine.Execute(MacroModel macro, INode currentPage)
at umbraco.macro.loadMacroScript(MacroModel macro)
at umbraco.macro.renderMacro(Hashtable pageElements, Int32 pageId)
(where line 8 of SecondLevelPageRedirection.cshtml is the Response.Redirect).
That problem and the ThreadAbortException itself are strongly suggesting to me that Response.Redirect is the problem here and I should be using some other means of performing this redirect. (And even if this weren't a problem I'd prefer to avoid the performance impact of a bunch of exceptions being thrown.)
How should we be performing this redirect to have the same effect (so anyone going to ~/section1/ will be redirected to ~/section1/page1-1/ and so on), without having to add an umbracoRedirect or umbracoInternalRedirectId to each node and without having these damn ThreadAbortExceptions thrown all the time?
As detailed in a handful of places (notably Why Response.Redirect causes System.Threading.ThreadAbortException? here on Stack Overflow and PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer on the MSKB), Response.Redirect(string) is only present in ASP.Net for backwards compatibility.
To quote from Joel Fillmore in his answer to the Stack Overflow question linked above:
The correct pattern is to call the Redirect overload with endResponse=false and make a call to tell the IIS pipeline that it should advance directly to the EndRequest stage once you return control:
Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();
This blog post from Thomas Marquardt provides additional details, including how to handle the special case of redirecting inside an Application_Error handler.
Note that code after the Context.ApplicationInstance.CompleteRequest call will execute, so may need handling separately.
Incidentally, as the problem stems from Response.End, which includes the code
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
then Server.Transfer will have precisely the same problem. There is more information at Is Response.End() considered harmful?

CQ5.5: getting Style of a target page

I've been working on this for sometime now, and I keep running into a wall. I think I'm close, but I figured someone out here in the land of SO might have some deeper insight if not a better way of doing what I'm trying to do.
Basically lets look at this scenario. I have a logo w/ some text that can be set from a few different places. If we look at the setup here is what it looks like.
Hiearchy:
Homepage [has designPath]
- Child Microsite Page [has designPath]
- Logo Component
Logic Flow (in logo component):
if properties.get("logoText") {
use this
} else if currentStyle.get("logoTextFromStyle") {
use this
} else if parentStyle.get("logoTextFromGlobal") {
use this
} else {
be blank
}
My query is with how to get the "parentStyle" of this page. Looking at the docs here: http://dev.day.com/docs/en/cq/5-5/javadoc/com/day/cq/wcm/api/designer/Style.html
I've been able to come up with the fact that I can get a Style object from the "designer" object made available via defineObjects. This is defined with the other utility objects like "pageManager, resourceUtil, resource, currentPage, etc".
With that being said this doesn't seem to work.
//assuming we have getting homePage earlier and it is a valid cq Page resource
Resource homePageResource.slingRequest.getResourceResolver().getResource(homePage.getPath());
Style homePageStyle = designer.getStyle(homePageResource);
at this point homePageStyle is null. To do some more testing I i tried passing currentPage.getPath() instead of homePage.getPath(). I assumed this would give me the currentPage resource and would in end yield the currentStyle object. This also resulted in a null Style object. From this I think I can safely conclude I'm passing the incorrect resource type.
I attempted to load the the cq:designPath into the resource hoping to get a Designer resourceType but to no avail.
I am curious if anyone has run into this problem before. I apologize if I've gone into too much detail, but I wanted to lay out the "why" to my question as well, just in case there was a better way overall of accomplishing this.
I've figured out how to return the style. Here is the rundown of what I did.
//get your page object
Page targetPage = pageManager.getPage("/path/to/target");
//get the Design object of the target page
Design homePageDesign = designer.getDesign(homePage);
//extract the style from the design using the design path
Style homePageStyle = homePageDesign.getStyle(homePageDesign.getPath());
it's very interesting the definition of "getStyle" is a little different from the designer.getStyle vs a Design.getStyle. designer.getStyle asks for a resource whereas Design.getStyle will take the path to a Design "cell" and return the appropriate Style.
I did some testing and it looks like it does work with inherited Styles/Designs. So if my cq:designPath is set at level 1 and I look up a page on at level 2 they will return the Design/Style at the cq:designPath set at level 1.
I hope this helps someone else down the way.
I tried this approach but was not getting the Styles in the Style object.
When we do this:
Design homePageDesign = designer.getDesign(homePage);
In this Design object we get the path till the project node i.e etc/design/myproject
After this if we try to extract the Style from the design path we do not get it.
However I implemented it in a different way.
In the design object, we also get the complete JSON of designs for(etc/design/myproject).
Get the sling:resourceType of the target page and get the value after last index of "/".
Check if this JSON contains the last value. If it contains, you can get your styles, i.e. image, etc.

Rails 4 with CanCan: unknown attribute error after including load_and_authorize_resource

I'm working in Rails 4 and have gotten CanCan to work well with instructions from this issue, except for one use case that I think might be relatively common.
I have a Comment model, which has_many :comments, through: :replies for nested comments. All of this is working well, until I add load_and_authorize_resource to my comments controller. The problem seems to stem from a hidden field sending an optional :parent_comment_id attribute to my create action.
I've permitted this attribute via strong parameters:
def comment_params
params.require(:comment).permit(:content, :parent_comment_id, :post_id, :comment_id, :user_id)
end
So that I can create the association if a :parent_comment_id is included:
if comment_params[:parent_comment_id] != nil
Reply.create({:parent_comment_id => comment_params[:parent_comment_id], :comment_id => #comment.id})
end
But once I add load_and_authorize_resource, I get an unknown attribute error for :parent_comment_id. What am I missing?
Solution came to me in my sleep. Here's what I did to solve the problem:
The only reason comment_params wasn't normally having a problem on create, was because I was excluding the extra :parent_comment_id parameter, like this:
#comment = post.comment.create(comment_params.except(:parent_comment_id))
When CanCan used the comment_params method however, it did no such sanitation. Hence, the problem. It would have been messy to add that sanitation to CanCan on a per-controller basis, so I did what I should have done all along and instead of passing the :parent_comment_id inside :comment, I used hidden_field_tag to pass it outside of :comment and accessed it through plain, old params.
I hope this helps someone else who makes a similar mistake!

Zend Framework isn't looking for camel cased actions when using the router

Hi guys im having a spot of bother, hope someone can shed some light on this.
For some strange reason my route comes up saying action does not exist unless i change the camel casing to all lower case for that actions name then it works fine. but then that goes against the naming conventions! and i dont want to make my code sloppy either.
Heres my route:
$FrontController = Zend_Controller_Front::getInstance();
$Router = $FrontController->getRouter();
$Router->addRoute("artistsave",
new Zend_Controller_Router_Route
(
"artist/save-artist",
array(
"controller"=>"artist",
"action" =>"saveArtist"
)
)
);
Now to me this should look in the ArtistController for the action saveArtistsAction, but it doesn't it throws up this error:
Whoops you encountered the below
error. Action "saveartist" does not
exist and was not trapped in __call()
So it appears to have removed my camel casing in the router as the a for Artist is now lower case in the error and if i rename my action to match that, it works!
Any idea's why it is not looking for saveArtist?
I realise I could just rename it to save as it is part of the artist object but now I have found this I would like to understand before coming unstuck some other time in the future.
Thanks in advance to any help :)
No soon as I sent this I figured it out, but I feel others may fall for the same mistake so best to leave this here and tell the solution!
In the router it is still in URL formatting I was meant to use hyphens not camel casing then the framework works it out. so here is my correction/solution:
$Router->addRoute("artistsave",
new Zend_Controller_Router_Route
(
"artist/save-artist",
array(
"controller"=>"artist",
"action" =>"save-artist"
)
)
);
Happy coding :)
The naming conventions specify that your actions should be named all lowercase up to the word "Action".
So the correct way to name actions is:
saveartistsAction()
somethingthatdoessomethingelseAction()

MVC 2 partial for edit/create return error

I got a question about MVC 2 and returning views for partials:
I got two views for creating and editing a user, the views both uses a partial so i can reuse the form fields.
UserPartial.ascx, EditUser.aspx, CreateUser.aspx
I got some logic in the controller post method (EditCreateUser) which finds out if its a new or existing user which is beeing submitted and this works fine.
The problem is when I try to return the edited user: return View(user). MVC complains about EditCreateUser file not existing. But thats only the method name, i want to return the object to the EditUser view which I am already on.
I could use RedirectToAction but i rather not because this problem would occur also if i want to return the same object when some errors has occured.
Any ideas on how to do this or some pointers in the right direction would be awesome.
Thanks
Within an action method named EditCreateUser, the statement return View(user) will by default look for a view with the same name as the action. You need return View("EditUser", user)