Can I have a grails controller named Office365Controller. More specifically is it allowed to have numbers in controller names? In url mapping i use office365 as controller. Could this be somehow conflicting with camel casing convention used for controller.
I ask this question because when i call a function inside this controller, i get tomcat error 403. My all other controllers are working fine and security for all of them is same.
Can I have a grails controller named Office365Controller.
Yes.
More specifically is it allowed to have numbers in controller names?
Yes.
I ask this question because when i call a function inside this
controller, i get tomcat error 403.
There may be some other factor in your app that is causing the issue, but I don't think the numbers in the controller name would cause a 403. A controller like this should work fine:
class Office365Controller {
def index() {
render retrieveSomeValue()
}
protected retrieveSomeValue() {
'hello world'
}
}
It isn't clear what might be going wrong in your app, but the answer to the questions quoted above is "yes".
Related
I wanted to put a random image on every viewpage of my mvc project. So i created a method that returns a partialView and call that method in the shared Layout page.
This works fine when I try to login with a correct username and password. The used is loged in and every page contains a random image. But when I give the invalid combination of username and password. The shared layout page does not find the controller I want to call with my #Html.Action and actualy the login view should be returned with an error message 'invalid combination of username and password' and ofcourse, with the random image.
InnerException:
{"A public action method 'RandomSponsor' was not found on controller 'Project.WebUI.Controllers.HomeController'."}
My Html.Action in shared layout.
#Html.Action("RandomSponsor", "Home")
Method in homecontroller.
[HttpGet]
[ChildActionOnly]
public ActionResult RandomSponsor()
{
var model = service.getRandomSponsor();
return PartialView("RandomSponsor", model);
}
The getRandomSponsor method works fine, this one always returns one random string value that is returned to the RandomSponsor.cshtml view.
RandomSponsor.schtml (only contains the image string)
<img src="~/Content/Images/Advert/#(Model)" alt="a" />
I searched the web for this problem but didn't found a solution, does anyone know the answer to this one?
Might it be something with HttpGet of HttpPost?
Regards.
If the executing request is a POST, then it will try to find a method RandomSponsor accepting HttpPost. If this makes sense, you could remove HttpGet and that should do the trick.
This can also happen if you have many layers of calls that start with a POST (I had an action returning a view returning a partial view calling RenderAction), then the call to RenderAction will still look for a POST method
Very similar to this problem that I had here - How to solve "public action method 'methodActionName' was not found on controller 'controllerNameController'"
And if you want to continue to accept the HTTP GET verb and fix the problem of cascading post request into a get request add this to your method
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
Keep in mind that [HttpGet] is the same as [AcceptVerbs(HttpVerbs.Get)]
This will happen if the request is a POST but the controller method is annotated [HttpGet]. For example, you might issue a POST that returns a view containing partial views called with #Html.Action, using controller methods annotated with [HttpGet]. If the original request is a POST, all of the controller methods subsequently called will need to support POST.
To fix it you can use the AcceptVerbs attribute to specify that your controller method accepts both POST and GET:
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Get)]
Received this error all of the sudden on several different PartialViews (not all of them) when customizing an install of MVCForum. We had not made any changes to the methods or views concerning the errors so it was really frustrating as to why they were broken.
After trying the other solutions on this post and others, went back through the changes made and what ended up stopping the errors was that we had changed the bindings in IIS to another domain that had the 'enforce lower case url' URL Rewrite rule enabled.
When we disabled the enforce lowercase rule, the errors stopped and the site worked as it was supposed to. It's not a URL Rewrite issue (I don't think) because we are able to enforce www using it with no errors. It's a lowercase rewrite issue. Didn't matter if we had the lowercase rule before or after the www rule.
This solution probably doesn't apply to many cases of this error, but it worked for us. Hopefully someone else can benefit from such a simple fix.
I just solved this issue strangely enough on my local PC, by making sure my entire request path was lower case. So give that a try.
I know this is a pretty old thread - but as it's top Google result I thought I'd add a potentially missing link for MVC.Net 5.2.6.
Scenario
I was attempting to call a child action via #Html.Action("ActionName", new { Id = 123})
and received an error much like the above, but none of the other solutions worked. I could hit the controller action externally (i.e. HttpGet), but the child action kept throwing the exception and was driving me nuts!
The solution I found
After two-ing and fro-ing for some time, I started playing with my routing attributes. I had the controller set up as:
[Route("{action}")]
[RoutePrefix("Prefix")]
[RouteArea("AreaName")]
As there was only one public action i wanted, "Index", I removed the {action} and placed an explicit route attribute on the public action and put my ChildActionOnly attribute back on the child.
After I did that, I hit the run and hey presto - the action was hit.
Might be worth a try if you're getting this error while using attribute routing. Note I did attempt to route the child action and this didn't work.
In my case, the same issue was happening randomly with the implicit :
using (Html.BeginForm())
Changing above to :
using (Html.BeginForm("Action","Controller", FormMethod.Post))
fixed this issue.
Did you give it a shot with Html.RenderAction? It is typically faster then Html.Action as it interact directly into the response stream as opposed to building a string.
You can view the following topics for more info:
What is the difference (if any) between Html.Partial(view, model) and Html.RenderPartial(view,model) in MVC2?
Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction
Another thing to note is that for Html.Action or Html.RenderAction, your view doesn't need to be in Shared folder, that is only required if you use Html.Partial or Html.RenderPartial
Anybody who already have implemented something similar using Grails could tell me please which are the good pratices (if there are any) to create user profile URLs with the format "http://www.myservice.com/username", as in Facebook, Twitter, Linkedin?
I'm trying to implement it through the UrlMappings and appears to me I'll need to break with the code conventions, at least for the Controllers.
So, any suggestions are welcome, thanks.
UPDATE 1
When I mentioned my concern about breaking the code conventions, what I'm saying is that I want to show the user profile using this mapping, but I do have other objects in my application which I would like to access using the default mapping:
"/$controller/$action?/$id?"()
SOLUTION
Thanks to the great contributions I've received here, I've camed up with this solution, which solves my problem.
As was pointed out, to do this kind of mapping, I'll need to control more closely how my requests are handled. That means I'll need to tell to Grails which controllers I don't want to be mapped to the "username" rule.
Since that will be a very tedious task (because I have several controllers), I did this to automate it:
UrlMappings.groovy
static mappings = {
getGrailsApplication().controllerClasses.each{ controllerClass ->
"/${controllerClass.logicalPropertyName}/$action?/$id?"(controller: controllerClass.logicalPropertyName)
}
"/$username/$action?"(controller: "user", action: "profile")
}
...
}
And of course, I'll need to do something similar in my user registration process to avoid usernames to be equal to some controller name.
That's it, thank you all.
Assuming you have a UserController and you are going to map any domain.com/username to the show action of user controller, your url mapping could be something like this :
In my example, name will become a parameter in your params.
for further details refer to here
Hope this helps.
static mappings = {
"/$name"(controller: "user", action: "show")
...
}
Given your requirements, everything after http://yourdomain.com/ can be a username or one of your other controllers, which can have undesired effects depending on which url mapping is defined first (e.g. user controller vs nonuser controller). But most likely the nonuser controller list will be the smaller list, so you should place that first and filter against it, then treat all other url mappings as user mappings.
Here is an example:
static mapping = {
"/$controller/$action?/$id?" {
constraints {
controller inList: ['nonUserController1', 'nonUserController2',...]
}
}
//this should work for /username and /username/whateveraction
"/$username/$action?"(controller: 'user')
}
Some things to note here:
you need to place the non user controller url mapping first, since everything else after http://yourdomain.com/ may be a username - correct?
second you need to place a constraint to catch all the non user controllers, while ignore the user url mappings
also you need to prevent a user from signing up with a username that matches one of your non user controllers
Somehow I have gotten sideways with my Grails MVC mapping and I do not understand how.
I have a controller, AController, which I generated using the Grails command line wizard. At a later date I generated a view for that controller to customize the view.
AController is in [project]/grails-app/controllers/[package]/AController.groovy and the view .gsp's are in [project]/grails-app/views/A/.
The URLMappings.groovy has:
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
When I run the application and enter a url of the form: localhost:8080/[project]/A/list I reach, as expected, the method A.list in AController.groovy.
However, when I then return from A.list expecting the framework to route to list.gsp in [project]grails-app/views/A/ I see a 500 error with the message:
"URL mapping must either provide a controller or view name to map to!"
Obviously I am doing something stupid but I cannot see what it was that I broke. URLMappings.groovy looks correct. File locations look correct. Scaffolding seems properly customized.
Any suggestions?
Du-Oh
The problem was that there was no .count for an array. For some reason my brain insists on .count and not .size(). Stupid human error.
I'm kind of new to grails and I'm trying to just map a basic URL request to a view.
So, say I have a view, /x/index.gsp and I want the user to be able to go to it. There will also be /y/index.gsp, /z/index.gsp, etc.
I defined it like so:
"/$customer/index" { view = {params.customer+"/index"} }
This seems to throw an exception though. I also have :
"/$customer/$controller/$action?/$id?" { }
which does work and I don't want to have to create a controller that doesn't really do anything but handle the index call and show it.
I'm sure I'm missing something simple but I don't know what it is.
The reason the first mapping fails is because it can't figure out what controller to route the request to.
To fix it, you need to define what controller you want the top mapping to route to. This is how I did this in a recent project of mine:
"/uploaders/$id" {
controller: "uploader"
}
To map to just a view:
"/$customer/index"(view: "/${params.customer}/index")
right, basically we have a link into our system that is all lowercase but that needs to be camel cased. rather than get the other developers to fix this, I want to just make the problem go away by url magic
"/myobj/$action?/$id?"{
controller: "myObj"
}
what i am trying to do is map anything that references controller myobj to controller myObj instead, and keep the action and everything else the same. The above code gives an exception, saying the
2010-07-11 18:14:50,021 ERROR [default] - Servlet.service() for servlet default threw exception
java.lang.IllegalArgumentException: URL mapping must either provide a controller or view name to map to!
however the following works
"/myobj/$action?/$id?"(controller: "myObj")
I dont understand, given the documentation. Why didnt the closure work? This is grails 1.2.0...
You should use
'/myobj/$action?/$id?' {
controller = 'myObj'
}
Edit
As a bit of explanation: the colon in the working example creates a map as described here (the working case is a Groovy function invocation with named parameters). Within the closure, you need to set the value of the controller property directly, i.e., using the equals sign.
This difference is demonstrated not specifically highlighted in the Grails URL mapping documentation.
Edit
Here's an untested method that may yield case insensitive controller mappings... maybe.
'$myController/$action?/$id?' {
grailsApplication.getArtefacts('Controller').find { it.name.toLowerCase() == myController.name.toLowerCase }.with { controller = it.name }
}
I'm assuming here (which I haven't verified) that the Grails application is available within the MappingCapturingClosure in the DefaultMappingUrlEvaluator.