MVC3 Routing - Routes that builds on each other - asp.net-mvc-3

I have an AREA setup in my project. I need to make the routes for the area progressive, meaning that the route will build on each other.
I'm looking at this as something like a link list. Each node in the list will have a reference to a parent. As move from left to right in the list it builds, and from right to left it removes.
In the area, I have companies and that have contacts, and child companies.
For example, I have companies that would have the following:
/Companies/list
/Company/{Id}
/Company/{id}/add
/Company/{id}/edit
/Company/{id}/delete
For the contact section I need to create the following routes:
/Company/{id}/contacts/list
/Company/{id}/contact/{id}/add
/Company/{id}/contact/{id}/edit
/Company/{id}/contact/{id}/delete
How do I make sure that /Company/{id} is always in the Contact and Child Company sections of the route?
I hope that I have made my question clear.

Subjective Generalities (take with a pinch of salt):
First off, you are using Company (singular) for companies, but then you are using contacts (plural) for the contacts. There is nothing wrong with this, from a structural point of view, but your users will thank you if you are consistent with your pluralizations. I would use the plural in both cases, but that is just my preference... it looks more like English.
You also use lower case for contacts, but upper case for Company. Doesn't look professional.
The next thing that is confusing is that you are using two {id} parameters, one for companies, one for contacts. I presume these are the ids for Company and Contacts respectively. But I am confused, but being human, I am able to deduce context unlike a computer. So you would be better of specifying the parameters in your routes. Ie:
/Companies/{CompanyId}/Contacts/{ContactId}/[action]
Answering your Question with an Example:
I get the feel you don't understand routes properly. If you did, your question would be more specific.
Your route parameters can come from a number of sources, depending on how the route is requested.
You could hard code it into a link. Or, more usefully, your route registration would be designed to catch requests that map to your Action signatures.
For example, I have an eLearning app with tutors, pupils, courses and steps (ie, the steps are like sections of a course, the pupil advances through the course step by step)
The route registration looks something like:
Route or Area Registration:
context.MapRoute(
"StepDisplay",
"Course/{CourseId}/Step/{StepOrder}/Pupil/{PupilName}/{TutorName}",
new { controller = "Course", action = "Display", TutorName = UrlParameter.Optional },
new[] { "ES.eLearningFE.Areas.Courses.Controllers" }
);
This route will catch a request from the following ActionLink:
ActionLink in View:
#Html.ActionLink(#StepTitle, MVC.Courses.Course.Actions.Display(Model.CourseId, step.StepOrder, Model.Pupil.UserName, tutorName))
Now, I just need to show you the Display action's signature:
CoursesController:
public virtual ActionResult Display(int CourseId, int StepOrder, string PupilName, string TutorName)
There are a few things to note here:
That I am able to call this specific route by giving the user a link to click on.
I construct this link using the Html.ActionLink helper
I have used David Ebbo's t4mvc nuget package so that I can specify the action I am calling and its parameters. By which I mean specifying the ActionResult parameter of the Html.ActionLink helper using:
MVC.Courses.Course.Actions.Display(Model.CourseId, step.StepOrder, Model.Pupil.UserName, tutorName)
If you think about it, what routes do is translate the url of a request into an action, so the parameters of my route are either the controller name, the action name or else they are the names of parameters in the action signature.
You can see now why naming two distinct route parameters with the same
name is such a bad idea (largely because it won't work).
So, look at your action signatures, and design your routes and your action links so that the everything marries up together.
MVC doesn't work by magic!! (Although the way it uses name conventions might lead you to believe it)

Related

Laravel 5.8 - one route two different controller action

In laravel 5.8, I have have 2 type of url.
/news/{category} - > send to news controller index action, if have category bind
/news/{news} - > send to news controller details action, if have news bind
Another case abort with 404.
How can i solve this problem?
In Laravel and almost all frameworks and routing systems I'm aware of, the Route and Controller/Action relationship is 1:1. Each route can only have one controller or action to handle it.
If I understand your question correctly, you have a single route pattern of /news/{parameter}, and you want one of three things to happen:
{parameter} contains a valid Category slug. Retrieve the category and display the appropriate view.
{parameter} contains a valid Article (details) slug. Retrieve the article and display the appropriate view.
{parameter} does not contain a valid category or article slug, and thus is not found. Return a 404 error.
You'll still need only a single controller action, but you can separate the logic to make it easy to understand:
routes/web.php:
Route::get('/news/{param}', 'NewsController#index');
app/Http/Controllers/NewsController (with pseudo code):
class NewsController extends Controller
{
public function index(string $param)
{
if ($category = Category::whereSlug($param)->first()) {
// Return your category view.
}
if ($article = Article::whereSlug($param)->first()) {
// Return your article view.
}
\abort(404);
}
}
I would personally recommend against sharing a common URL structure for two different entity types like this. It opens the possibility for name conflicts (a Category and Article have the same slug) and can make the user experience confusing. (It might hurt search engine optimizations or results, also, but that's just speculation - I don't have anything to confirm or deny that.)

Laravel unique user profile url like facebook

Assume I have a site with a unique URL for users, e.g. abc.com/user1.
I want users to be able to create their own user urls like abc.com/user1 to abc.com/foo
The problem here is that my site has static pages such as: about, help, contact, download.
On the profile page, when users change their url, i apply this validator to their new profile url:
'username' => 'required|alpha_dash|max:20|min:3|unique:users'
In this situation, if the user chooses their new profile url to the same as a Route of my app (help, about, download...), their URL looks like: abc.com/about, this is troublesome.
Of course, the Validator will return true because that name is valid: min=3, max=20 and unique in "users" table ( "users" table not contains any control, of course).
To solve this, I add name of some Route to "users" table (about,contact,download...), so they cannot make their profile URL like abc.com/about,
But this is not good idea, because I might add more Routes in future.
PS: I dont like URL like abc.com/profile/user1, must be abc.com/user1.
Please help me to solve this.
You can use Route::getRoutes() to get all registered routes in your application
$routes = Route::getRoutes();
foreach($routes as $route){
echo $route->getUri(); // getUri will return the url pattern it matches
}
Now you can use this to check if the username doesn't appear in your routes.
But be careful! If you want to add routes in when the application is running you will have to check everytime that there's no user that has taken the name you want to chose.
Here are some possibilities
1. Call static page routes first
You can either call the static routes first and then at the end you do a catchall like lukasgeiter suggested, or you might even do a check in the controller and go through your static pages first. The problem here is that the user can create the user (e.g. "about") but then when they call that page, they would see the about page, even though they've correctly created the username, this might create a confusion.
2. Blacklist
Another way would be to create a blacklist for these usernames, so that people can't even register these types of usernames (this would be similar to your solution of pre-creating those usernames, but this way would be a bit cleaner and more easily expandable). Using this you will always have the trouble that someone will have used the username, once you want to use it as a static page. E.g. when you want to expand into another country.
3. Static pages on one level lower
E.g. you can create the static pages one level lower, such as abc.com/static/about, so there would be no clash.
4. Prepend character before username
This is the way I went, because the other ways were technically a bit too risky for me. So I chose the '#' sign for my users. So abc.com/#ThisIsMe is my current solution. It works in different languages (as opposed to abc.com/profile/thisisme would only work in languages, where profile is the correct term)
I think Flickr went from flickr.com/username to flickr.com/photos/username. Google+ doesn't really let you decide, but makes suggestions (AND adds the +). Twitter and Facebook let users choose their own, I would assume they have a blacklist. LinkedIn uses /in/.

Routing to Controller in Laravel4

I am using laravel for the first time and need some help understanding routes. I am setting up a view that will show a list of orders placed by customers. Above this list are 2 search boxes. One for searching by ID, the other for selecting a date. I'd like to have a "default" route so when id/date are NOT included in the route, we see all orders placed so far today.
Routes should be as follows:
orders - Should display all orders placed today.
orders/{id} - Should show only the specific order that belongs to that id.
orders/{date} -
Should show all orders placed on a specific date.
{id} and {date} should be distinguished by regular expressions.
I can get any one of the routes to work by themselves but when I try to create the routes for all 3 and modify my controller accordingly I break the others. One example is this:
Route::get('orders/{id}', 'OrderController#getOrders')->where('id', '[0-9]+');
Which works for getting the order by ID, but if I wanted to allow for dates as well I would have to change the route entirely. From that point I'd like to be able to go even further, for example the route orders/12345/edit should bring me to the view that allows me to edit the order.
How can I properly setup my routes/controller to do this?
Unless you manage to write a regular expression that validates dates or numeric values you have two options:
Write two different routes: one that validates dates and other that validates IDs. Both would point to different methods in the controller.
Use one route that doesn't validate its the parameter and that points to one method in the controller where the type of parameter would be checked for date or ID.
I like the first option better, because I believe both routes are similar yet very different.
EDIT
If you want to use the same form to target to different urls depending on the contents of inputs you have to use javascript, you can change the action in the form using:
$('#form').attr('action', "the_url");
And you'd have to set up a listener for the inputs to know which url to point to:
Detecting input change in jQuery?
I hope this helps you!
just make three routes like laravel documentation
orders route:
Route::get('orders', 'OrderController#getOrders');
orders by id route:
Route::get('orders/{id}','OrderController#getOrdersById')->where('id', '[0-9]+');
orders by data route:
Route::get('orders/{data}', 'OrderController#getOrdersByData')->where('name', '[A-Za-z]+');
also you can create three route into your OrderController like documentation

MVC Routing Engine routes same formatted route to different controller actions

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

MVC in yii: how to build pages with several actions belonging to different models

I would like to know how you should write website pages that use for example 3 models and several actions on them.
Because there is usually only a controller involved with a page call and only a special action.
For example:
there should be a page which displays a group of people, and on that page I can edit the peoples names and assign new people to the group and i can add people as new managers of a group.
Does this page need its own controller or how do I program such pages?
Using your scenario, here is how I would set things up:
The controller you'd use for all related actions would be 'Group' (in Yii, 'ControllerGroup')
For your main page that displays the group of people, you could make an action in your Group controller called 'manage' (in Yii, the method name would be actionManage). Assuming you aren't going an Ajax route, for each person on the manage page you may have a link to edit that person. The links would point to the 'update' action. For adding, you'd want an action 'add'.
Your models involved would likely be User, Group, and UserGroup and you'd use them as necessary in any controller you have.
Actions can belong only to controllers. In each action you can work with any models of your application. In your case you must create a UserController and a list of actions (e.g. actionViewList, actionEdit, actionAssignToGroup).
Check this for more information: Yii Controller

Resources