How can I implement a "slug" (I believe is the right term) in the URL? Say the URL is
www.example.com/module/controller/action1/123
or
www.example.com/module/controller/action1/123/abc
and I want my action1 controller action method hit, and I want to be able to access the value 123, or even 123 and abc, how could I do that?
public function action1Action()
{
$request = $this->getRequest();
$data = $request->getParams();
var_dump($data);
}
Magento uses next scheme to access values in url (aside from normal GET request):
www.example.com/module/controller/action1/[key]/[value]/[key2]/[value2]
In the controller method action1Action you'll use
$value1 = $this->getRequest()->getParam('[key1]'); // [value1]
$value2 = $this->getRequest()->getParam('[key2]'); // [value2]
Related
Being inside controller action or view, is there any way to know which controller/action user has been just redirected from? There is Request.UrlReferrer, but it's Url, I need to know Controller and/or action names instead.
There is Request.UrlReferrer, but it's Url, I need to know Controller and/or action names instead.
Given an Url as string you could parse it and obtain the corresponding controller and action names using the following approach:
var url = new Uri("http://example.com/somecontroller/someaction?foo=bar");
var request = new HttpRequest(null, url.AbsoluteUri, url.Query);
var response = new HttpResponse(StringWriter.Null);
var httpContext = new HttpContext(request, response);
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
string controllerName = (string)routeData.Values["controller"];
string actionName = (string)routeData.Values["action"];
Obviously at the place where I used http://example.com/somecontroller/someaction?foo=bar you could use Request.UrlReferrer.AbsoluteUri.
Needless to say that this approach is absolutely unreliable. A much better solution is to simply pass the required information as parameters to the controller action from the calling action.
I have a Kohana 3 MVC application.
In a view, I can explicitly call a controller's action with this line:
Request::factory('/test/deliveryaddress')->execute();
But I want to also send a parameter to the action as well to be processed like this:
public function action_deliveryaddress($region_name = NULL)
{
$view = new View('test/deliveryaddress');
$region_name = isset($_GET['region_name']) ? $_GET['region_name'] : '';
$view->set('region_name', $region_name);
$this->request->response = $view;
}
I've tried these two attempts but they don't work:
Request::factory('/test/deliveryaddress?region_name=top')->execute(); //error
Request::factory('/test/deliveryaddress', array('region_name'=>'top'))->execute(); //ignored
How can I send a GET variable with Request::factory() or is there a better way to send GET parameters to an action?
For 3.1, you can use the query() method of the Request class:
equest::factory('/test/deliveryaddress?)->query('region_name', 'top')->execute();
For 3.0, there is no real isolation, and you have to manipulate the $_GET array.
use query() from Request class and in your controller
instead of:
$region_name = isset($_GET['region_name']) ? $_GET['region_name'] : '';
try:
$get = $this->request->query();
$region_name = isset($get['region_name']) ? $get['region_name'] : '';
Is there a way within asp.net MVC 2 whereby I can route a request and have a portion of the URL ignored and passed to the controller as a variable?
My needs state that I must store pages dynamically in a database, and they should be accessible by looking at the URL and reading the URL segments to find the relevant page. Effectively, I need a Site controller, to which the remaining portion of the URL will be passed.
Site-Controller/this/is/a/page
So this in case the site controller would pick up the /this/is/a/page 'string'
Is this possible?
Thanks!
Yes, use a wildcard route, like:
routes.MapRoute(
"SiteController", // Route name
"Site-Controller/{*url}", // URL with parameters
new { controller = "SiteController", action = "Index" }, // Parameter defaults
null // constraints
);
Then your action looks like:
public ActionResult Index(string url)
{
}
Create a wildcard Route in Global.asax which captures everything after the first segment of the url and passes it to your Action method:
routes.MapRoute("Page",
"Site-Controller/{*urlsegments}",
new {
controller = "Site-Controller",
action = "YourAction",
urlsegments = ""
});
Make sure your Action method accepts a 'urlsegments' parameter and you can work with it from there:
public ActionResult YourAction(string urlsegments)
{
// Do something with the segments here
}
I am creating a modular ASP.NET MVC application using areas. In short, I have created a greedy route that captures all routes beginning with {application}/{*catchAll}.
Here is the action:
// get /application/index
public ActionResult Index(string application, object catchAll)
{
// forward to partial request to return partial view
ViewData["partialRequest"] = new PartialRequest(catchAll);
// this gets called in the view page and uses a partial request class to return a partial view
}
Example:
The Url "/Application/Accounts/LogOn" will then cause the Index action to pass "/Accounts/LogOn" into the PartialRequest, but as a string value.
// partial request constructor
public PartialRequest(object routeValues)
{
RouteValueDictionary = new RouteValueDictionary(routeValues);
}
In this case, the route value dictionary will not return any values for the routeData, whereas if I specify a route in the Index Action:
ViewData["partialRequest"] = new PartialRequest(new { controller = "accounts", action = "logon" });
It works, and the routeData values contains a "controller" key and an "action" key; whereas before, the keys are empty, and therefore the rest of the class wont work.
So my question is, how can I convert the "/Accounts/LogOn" in the catchAll to "new { controller = "accounts", action = "logon" }"??
If this is not clear, I will explain more! :)
Matt
This is the "closest" I have got, but it obviously wont work for complex routes:
// split values into array
var routeParts = catchAll.ToString().Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
// feels like a hack
catchAll = new
{
controller = routeParts[0],
action = routeParts[1]
};
You need to know what part is what in the catchAll parameter. Then you need to parse it yourself (like you are doing in your example or use a regexp). There is no way for the framework to know what part is the controller name and what is the action name and so on, as you haven't specified that in your route.
Why do you want to do something like this? There is probably a better way.
Given a url that follows the following pattern:
firstcolor={value1}/secondcolor={value2}
where value1 and value2 can vary and an action method like:
ProcessColors(string color1, string color2) in say a controller called ColorController.
I want the following route evaluation:
URL '/firstcolor=red' results in a call like ProcessColors("red", null)
URL '/secondcolor=blue'results in a call like ProcessColors(null, "blue")
URL 'firstcolor=red/secondcolor=blue' ends up in a call like ProcessColors("red", "blue")
Now from I think this can be achieved with a few routes, something like this
route.MapRoute(null,
"firstcolor={color1}/secondcolor={color2}",
new { controller=ColorController, action = ProcessColors })
route.MapRoute(null,
"firstcolor={color1}}",
new { controller=ColorController, action = ProcessColors, color2 = (string)null })
route.MapRoute(null,
"secondcolor={color2}}",
new { controller=ColorController, action = ProcessColors, color1 = (string)null })
This is sufficient for just 2 colors, but as far as I can tell we'll end up with a proliferation of routes if we wanted to have, say 4 colors and be able to have URL's like this:
'/firstcolor=blue/secondcolor=red/thirdcolor=green/fourthcolor=black'
'/firstcolor=blue/thirdcolour=red'
'/thirdcolour=red/fourthcolour=black'
and so on, i.e. we need to cater for any combination given that firstcolor will always be before 2nd, 2nd will always be before 3rd and so on.
Ignoring my ridiculous example, is there any nice way to deal with this sort of situation that doesn't involve lots of routes and action methods needing to be created?
First of all, if you are going to use that key=value format, then I suggest using QueryString instead of the URL.
But if not, you can do this :
//register this route
routes.MapRoute("color", "colors/processcolors/{*q}",
new { controller = "Color", action ="ProcessColors" });
Then in your ColorController :
public ActionResult ProcessColors(string q) {
string[] colors = GetColors(q);
return View();
}
private string[] GetColors(string q) {
if (String.IsNullOrEmpty(q)) {
return null;
}
return q.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
In this case your URLs will be like this :
site.com/colors/processcolors/red
site.com/colors/processcolors/red/green
In the case that we use the wildcard mapping I suppose we lose the ability to use Html.ActionLink to build our URL's for us?