Route to more than one homecontroller - asp.net-core

I have in the controller folder like this:
-Controller(Main Folder)
-HomeController(Main Controller)
-HomeBasic1Controller
-HomeBasic2Controller
-HomeBasic3Controller
-HomeBasic4Controller
When I execute the program, first it´s going to HomeController, until here everything is correct, then in HomeController I can call to any controller, I can go to HomeBasic1Controller or to any other HomeBasicXController.
The problem is in the URL, it´s showing like this
http://localhost:XXXXX/HomeBasic1
but I want to be like this
http://localhost:XXXXX/Home
no matter from which controller is calling!

The easy way to do this is to put all your actions on the Basic1,2,3, and 4 controllers all on HomeController. This is the generally accepted convention. If you can't do that, then what you want is "custom routing". The straightforward way to start this approach is to add a route for each action in Basic1 with each specific URL. A single route might look something like this:
routes.MapRoute(
"Basic1SomeAction",
"home/someaction",
new { controller = "HomeBasic1", action = "SomeAction" }
);

Related

use fix route in asp.net core api

I'm converting my code to Asp.net core 3.1 in a web api project. my code is something similar to bellow:
When i call http://localhost:44307/PersonDetails I would like to get "Result1" and when i call http://localhost:44307/Person/2207 i should get "result2".
The first route works as i expected but for the second one, I get 404. it works if i call http://localhost:44307/PersonDetails/Person/2207 but it is not what i expected.
Appreciate if you could help me.
Try it like below:
[HttpGet]
[Route("~/Person/{personId}")]
public ActionResult<Person> Get([FromQuery]int personId)
{
return Ok("result2");
}
When you add ~ before it, it will ignore the route attribute on your controller.
[Route("[controller]")]
when you use a route on your controllers, all child actions will use that. so in this case, because your controller name is PersonDetails you have to enter the controller name in your URLs.
but, you can use this trick :
step1: remove this line:
[Route("[controller]")]
step2: add PersonDetails to your Get method
[Route("PersonDetails")]
Public ActionResult Get()

Is there a named routes and default params equivalent for Razor Pages page routes?

I have a JobPosts/Index page with multiple GET parameter bindings to allow filtering: let's take CityId and IsRemote for example. I don't want these to be passed as query string parameters, instead I want to use friendly routes for them. So I have defined these:
options.Conventions.AddPageRoute("/JobPosts/Index", "cities/{cityId}/jobs");
options.Conventions.AddPageRoute("/JobPosts/Index", "remote-jobs");
options.Conventions.AddPageRoute("/JobPosts/Index", "jobs");
The routes work just fine when I type them in the browser and the CityId one is bound properly, but two things are missing.
First, there is no way to specify a default value for my IsRemote param, which I want to set to true ONLY when using the remote-jobs URL.
And second, when trying to generate a URL like this:
<a asp-area="" asp-page="/JobPosts/Index" asp-route-cityId="#Model.CityId"></a>
I get the following URL:
https://localhost:44391/jobs?cityId=2265885
When what I actually expect is:
https://localhost:44391/cities/2265885/jobs
So it looks like the tag helper or the part responsible for constructing the URL doesn't look at all at the different routes to try and get a best match based on the list of parameters. Actually, it will always use the last page route defined for that page.
Nor do I have the option anywhere to specify a route name for the page route and then use asp-route to explicitly say which route I want.
Any ideas how to achieve that? Or if it's something that's on the roadmap for Razor Pages?
EDIT: Hardcoding the href is not an option. I want this to go through the proper routing services as there are other things to be done as well, like generating culture-specific URL for non-english users (eg. {cultureId}/cities/{cityId}/jobs - this is done through route conventions. Hardcoding the href would obviously bypass that.
There is a easy way to set IsRemote default value.
public bool IsRemote { get; set; } = true;
This tag asp-page will link to Page /JobPosts/Index.csthml directly,
https://localhost:44391/JobPosts?cityId=2265885
= https://localhost:44391/JobPosts/Index?cityId=2265885
If you are looking forward the URL https://localhost:44391/jobs?cityId=2265885
you could try this a tag to request.
Go to JobPosts
———————————————————————————————
Using a middleware to handle /remote-jobs
app.Run(next => async context =>
{
if (context.Request.Path == "/remote-jobs")
{
return View with default IsRemote
}
});

Same paginator for every controller in ZF2

I'm writing my first app in ZF2, and I want to create pagination system.
Currently, I have something like this in my controllers:
$pagLimit = $this->params()->fromQuery('limit', 1000);
$pagPage = $this->params()->fromQuery('page', 1);
$orderDir = $this->params()->fromQuery('dir', 'ASC');
$orderBy = $this->params()->fromQuery('column', 'id');
$result = $this->getMapper()->getList($orderDir, $orderBy);
$paginator = new Paginator(new ArrayAdapter($result));
$paginator->setItemCountPerPage($pagLimit);
$paginator->setCurrentPageNumber($pagPage);
I think that my solution is not quite good..
If I want to change e.g. default limit of items per page, I have to modify all my controllers. Also, I have to remember to send two arguments for all mapper methods which are getting lists of data.
My first thought was to use inheritance ("MyController" with methods like: setPaginationParams(), and setPaginator($data)).
Then I would have to remember to invoke "my controller" methods in every controller.
But maybe there is a better way to implement the same paginator for every controller in my module? MVC event? Create custom class and use DI?
What is the best way to implement this functionality?
Could you just give me some hints?
I'm new to ZF2 and OOP concepts. :(
You could always extend the paginator with your own, and have default values set.
You could even just pass in the request object or params object and then let the Paginator internally handle some things for you to save setting up default values etc.

How do you check if the current page is the frontpage using YII?

Drupal has a function called "drupal_is_front_page". Does YII have something similar to deal with navigation in this way?
Unfortunately not. And while the information needed to piece this together is available, doing so is really more pain than it should be.
To begin with, the front page is defined by the CWebApplication::defaultController property, which can be configured as discussed in the definitive guide. But there's a big issue here: defaultController can in reality be any of the following:
a bare controller name, e.g. site
a module/controller pair, e.g. module/site
a controller/action pair, e.g. site/index
a module/controller/action tuple, e.g. module/site/index
If you have specified the defaultController as #4 (which is the same as #3 if your application does not include any modules) then everything is easy:
function is_home_page() {
$app = Yii::app();
return $app->controller->route == $app->defaultController;
}
The problem is that if defaultController is specified as #1 or #2 then you have to examine a lot of the runtime information to convert it to form #3 or #4 (as appropriate) so that you can then run the equality check.
Yii of course already includes code that can do this: the CWebApplication::createController method, which can accept any of the valid formats for defaultController and resolve that to a controller/action pair (where controller is dependent on the module, if applicable). But looking at the source doesn't make you smile in anticipation.
To sum it up: you can either assume that defaultController will always be fully specified and get the job done with one line of code, or borrow code from createController to determine exactly what defaultController points to (and then use the one line of code to check for equality).
I do not recommend looking into solutions based on URLs because the whole point of routes is that different URLs can point to the same content -- if you go that way, can never be sure that you have the correct result.
In my experience, there is no such function in Yii. However, you can retrieve the followings:
base url: Yii::app()->request->baseUrl
current URL : Yii::app()->request->requestUri.
current page controller with Yii::app()->getController()->getAction()->controller->id .
With these APIs, it should be possible to find out whether the current page is front page.
another simple idea:
in your action (that one you use to present your 'main front page'), you could set up a variable using a script in its view:
Yii::app()->getClientScript()->registerScript("main_screen",
"var main_front_page = true;",CClientScript::POS_BEGIN);
put that code in the "main view", (the rest view pages dont have this piece of code).
so when you need to check if a page is the "main page" you could check for it using javascript, quering for:
if(main_front_page){..do something..}.
if you need to recognize the main page in php (in server side), use the method proposed by Jon.
another solution, based on a common method for your controller:
Your controllers all of them must extend from CController, but, when you build a new fresh yii application Gii creates a base Controller on /protected/components/Controller.php so all your controllers derives from it.
So, put a main attribute on it, named:
<?php
class Controller extends CController {
public $is_main_front_page;
public function setMainFrontPage(){ $this->is_main_front_page = true; }
public function getIsMainFrontPage(){ returns $this->is_main_front_page==true; }
}
?>
well, when you render your main front page action, set up this core varible to true:
<?php
class YoursController extends Controller {
public function actionPrimaryPage(){
$this->setMainFrontPage();
$this->render('primarypage');
}
public function actionSecondaryPage(){
$this->render('secondarypage');
}
}
next, in any view, you could check for it:
<?php // views/yours/primaryview.php
echo "<h1>Main Page</h1>";
echo "is primary ? ".$this->getIsMainFrontPage(); // must say: "is primary ? true"
?>
<?php // views/yours/secondaryview.php
echo "<h1>Secondary Page</h1>";
echo "is primary ? ".$this->getIsMainFrontPage(); // must say: "is primary ? false"
?>

Yii framework urlManager rewrite rules

I have a url that looks like this:
<controller>/<action>/param/value
and I want it to like something like this:
param/value
How can it be achieved?
I tried this rule but not sure if it's ok (controller is account and action is index).
'user/<user:.*>' => 'account/index/user/test'
If I uderstand your question correctly, you want to handle URL's like this:
mysite.domain/user/username123
And call actionIndex in AccountController with param User, which (in this case) equals "username123"
In this case you can try the rule below:
'user/<user:.*>' => 'account/index/<user>'
But maybe you will need to change the declaration if your action:
function actionIndex($user){
// code
}
I would avoid putting params into action signatures as yii doens't go about processing actions with mismatching signatures [gracefully] at all... In fact, putting $user in will bind that action to always need a $user specified and if you ever decide to change your functionality, tracking down why your action isn't being called would be harder than determining why your $_GET isn't set... I would suggest in stead of adding the $user into the signature, just do something as follows in your action.
//will always run on /user/<USER:.*>
function actionIndex(){
$user = isset($_GET['user'])?$_GET['user']:NULL;
if(!is_null($user)){
//your user specific account action..
}else{
//handle your error gracefully..
}
}
This approach lets your action be more versatile. The URL rule should be as follows:
'user/<user:.*>' => 'account/index/user/<user>' //user is defined as a get...
Hope that helps && happy coding!