Suppose I:
Have a route {controller}/{action}/{id} in my Global.asax file.
A Controller Foo and Action Bar(String id) returning a view.
A very simple View containing a URL rendered by #Url.Action("bar", "foo") - explicitly NOT specifying an id.
If I browse to /foo/bar/test, the view will show the rendered URL as /foo/bar/test. I would have expected that it should be /foo/bar as I didn't specify a value for id.
Why would it include the current id even when I didn't specify it, and is there any way of preventing this (apart from 'hard-coding' the URL directly)?
You did specify the value for id when you put /foo/bar/test in the browser address bar. You are essentially calling the method Bar with the parameter "test" in your foo controller. Your simple view is irrelevant when you browse directly.
To answer your last question you may need to have a re-look at the way you are using MVC.
I believe this is a regression bug in MVC3, as discussed by Phil Haack here: http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx
This is the correct answer: https://stackoverflow.com/a/7133304/27938
Related
I am working on a TYPO3-backend-module. The main "overview"-Action allows to upload a file via ajax upload, which gets processed in one of my controllers.
The corresponding controller-action instantiates a StandaloneView, renders it and writes the rendered content to the response body.
My problem is, that I have no controllerContext set in the generated content, therefore a form, which should trigger a different extbase action, in that rendered content does not work, because the modulename is not set.
Can anybody tell me how I could possibly get/pass the controllerContext, to make it available in the controller action, which is called via ajax ?
Best regards and thanks in advance, Oliver !
The main problem here is that BE modules don't exactly use a standard View implementation - in the default implementation, they wrap around a StandaloneView which by definition has no controller context.
That being said, if you can change the way the View wraps around the StandaloneView, the controller context can be copied by doing:
$view->getRenderingContext()->setControllerContext($parentView->getRenderingContext()->getControllerContext());
Alternatively you may want to copy the entire rendering context rather than just the controller context.
Advise applies to TYPO3v8 only. On 7.6 you will need to copy the Request instead.
For usages outside of MVC context you will need to manually pass the original controller context values such as controller name and module name. That means the values must be part of the link you create and must be read by the receiving code (in whichever way that code's context requires) and then manually assigned to a Request you create and pass to the sub-view. Note that this is only necessary if those MVC context values actually change - if you always call the same action next, you can get the right result by simply hardcoding the desired extension name, module name, controller name and action in the form/link in the template you render from that AJAX controller.
I have limited knowledge so beat me up as needed.
I have created a controller using the EF with ASPX(C#) views. I inherited this setup.
The PK in the target table/EF is an actual URL. So when you click the link ActionLink feeds the URL and I receive a 404.
Html.ActionLink("Edit", "Edit", new { id=item.ImagePath })
So id= /foldername/foldername2/image.jpg
This causes the browser to try and load the resource.
Can someone give me a clue how to process this "id" accordingly?
Have you changed your routing to accept this sort of id?
If not then you will need to go into your global.asax.cs file and edit the map routes.
This should help you with that:
Creating custom routes
The EDIT action in the controller... is waiting for a string ID or Integer one?
If the EDIT action accepts strings, then you could just scape the ID's "/"... that way the routing engine will no think the ID is a URL.
Is it possible to set the absoluteURI in the controller after clicking on an action link? So for example:
User clicks on a link called "GoHere". The current URL is domain.com/section/place. When the link hits the method in the controller, it recognizes that the user is currently in a section called "section", even though in the file structure section doesn't exist. The link itself actually points to domain.com/place2. Instead of returning a URL of domain.com/place2, it returns domain.com/section/place2.
The reason I ask is because for what I'm doing, the section is completely arbitrary and doesn't exist. It's just there to give the impression that the user is in another section. I know I could create extra sets of controllers, but I'm trying to get around this since for management purposes it's better if I just have one set of controllers. Is this possible? Thanks.
In your gobal.asax, try setting your route to require section for the control. Maybe "{control}/section/{action}/" and whatever else you need.
Okay, I did my homework and search SO, and indeed I found similar questions but not reporting the behavior I'm getting.
Here is the deal, I have defined a route:
routes.MapRoute("CategoryName", "Category/Name/{text}",
new { controller = "Category", action = "Name", text = "" });
The twist here is the following:
This url: http://www.url.com/Category/Name/existingCategoryName
And this url: http://www.url.com/Category/Name/anotherExistingCategoryName
Both url's should go to the same controller method which is public ActionResult Name(string text) but sadly the first url is going to the default Index method, the second is being routed correctly.
I wonder why this happens, as I've been with .net mvc for several years and never experienced this behavior.
As a side note here are some facts:
As it's being route to different methods, I doubt the code inside them has something to do with it.
When manually write the category to something it doesn't exists in the DB as a category name it goes through the Name method.
The routes are placed correctly, as I'm aware the first route that matches the pattern will win.
Even I tried place the CategoryName route first, the behavior is the same.
When writing each link in the Category/Index I use the same #Html.RouteLink() helper, so all the links are formatted the same way.
Thanks in advance!
Are you using the - sign in the failing route?
Maybe you can find more information with the Routing debugger
And maybe you can look at this question: Failing ASP.NET MVC route. Is this a bug or corner case?
Phil Haack also give an possible answer to your problem in: ASP.NET routing: Literal sub-segment between tokens, and route values with a character from the literal sub-segment
I have a tiny application in MVC 3.
In this tiny application, I want my URLs very clear and consistent.
There's just one controller with one action with one parameter.
If no value is provided (that is, / is requested by the browser), then a form is displayed to collect that single value. If a value is provided, a page is rendered.
The only route is this one:
routes.MapRoute(
"Default",
"{account}",
new { controller = "Main", action = "Index", account = UrlParameter.Optional }
);
This all works fine, but the account parameter never appears in the address line as a part of the URL. I can manually type test.com/some_account and it will work, but other than that, the account goes as a post parameter and therefore does not appear. And if I use FormMethods.Get in my form, I get ?account=whatever appended to the URL, which is also not what I want and which goes against my understanding. My understanding was that the MVC framework would try to use parameters set in the route, and only if not found, it would append them after the ?.
I've tried various flavours of setting the routes -- one route with a default parameter, or one route with a required parameter, or two routes (one with a required parameter and one without parameters); I've tried mixing HttpGet/HttpPost in all possible ways; I've tried using single action method with optional parameter string account = null and using two action methods (one with parameter, one without), but I simply can't get the thing appear in the URL.
I have also consulted the Steven Sanderson's book on MVC 3, but on the screenshots there are no parameters either (a details page for Kayak is displayed, but the URL in the address bar is htpp://localhost:XXXX/).
The only thing that definitely works and does what I want is
return RedirectToAction("Index", new { account = "whatever" });
But in order to do it, I have to first check the raw incoming URL and do not redirect if it already contains an account in it, otherwise it is an infinite loop. This seems way too strange and unnecessary.
What is the correct way to make account always appear as a part of the URL?
My understanding was that the MVC framework would try to use
parameters set in the route, and only if not found, it would append
them after the ?
Your understanding is not correct. ASP.NET MVC doesn't append anything. It's the client browser sending the form submission as defined in the HTML specification:
The method attribute of the FORM element specifies the HTTP method used
to send the form to the processing agent. This attribute may take two
values:
get: With the HTTP "get" method, the form data set is appended to the URI specified by the action attribute (with a question-mark ("?")
as separator) and this new URI is sent to the processing agent.
post: With the HTTP "post" method, the form data set is included in the body of the form and sent to the processing agent.
ASP.NET MVC routes are used to parse an incoming client HTTP request and redispatch it to the corresponding controller actions. They are also used by HTML helpers such as Html.ActionLink or Html.BeginForm to generate correct routes. It's just that for your specific scenario where you need to submit a user entered value as part of the url path (not query string) the HTML specification has nothing to offer you.
So, if you want to fight against the HTML specification you will have to use other tools: javascript. So you could use GET method and subscribe to the submit handler of the form and inside it manipulate the url so the value that was appended after the ? satisfy your requirements.
Don't think of this as ASP.NET MVC and routes and stuff. Think of it as a simple HTML page (which is what the browser sees of course) and start tackling the problem from that side. How would you in a simple HTML page achieve this?