MVC 3 dynamic routing for hosted site - c#

I'm working on an MVC 3 site hosted by GoDaddy and I need to store dynamic variables in the URL. Something like:
http://www.example.com/{Cat}/{List}/{Item}/{Action} or
http://{Cat}.example.com/{List}/{Item}/{Action}
The latter would be the best.
The site allows users to create custom lists, list categories, and list items. A list category could be something like Sports or News, a list could be NBA Teams or Politics, and a list item would be Lakers or Pres. Obama. The user is able to generate any one of the 3 (only no duplicates).
My goal is to make the URL be something like http://sports.example.com/nba/lakers and have the user routed to Controller = "Items", Action = "Details", with params Cat = "sports", List = "nba", Item = "lakers" and if the user specifies an Action (like Edit, Delete, etc), it replaces Details.
I'm not super familiar with IIS (more specifically IIS via GoDaddy), so IDK if the subdomaining would work (but that is the ultimate goal) and if it is possible, I'd like to know what I would need to do (i.e. self host + steps).
Thanks

this section is a domain http://sports.example.com/ translating to physical address e.g. 203.10.01.1 you'll have to register a subdomains with GoDaddy. ASP.NET MVC will handle ... nba/lakers section. So your domain will be http://sportworldwide.com/ with subdomains like http://nba.sportworldwide.com/lakers. If want to use MVC 3 only. try something like
sportworldwide.com/sport/nba/lakers.
routes.MapRoute("DefaultSport", "sport/{action}/{id}",
new { controller = "Sport", action = "", id= "" });
EDIT:
I can't comment too much on wildcard DNS records performance or etc. The only problem I see is you'll need to write a custom route handler, then you'll need to get the subdomain part of Url e.g. sport and change the action or id value to handle your subdomain urls.
here is example of modifying the route through a routehandler:
asp.net MvcHandler.ProcessRequest is never called

Related

Creating a dynamic route

I am trying to create dynamic routes using ASP.Net Core and Razor Pages. Basically, I have two razor pages. One is called Pages/Home.cshtml and another is called Pages/Calendar.cshtml. Each user that logs in has their own username. So let's say I have two users in my database, Sam and Jessica and let's say Sam is logged in and goes to http://www.example.com/Sam, then it should render Pages/Home.cshtml. If Sam is logged in and goes to http://www.example.com/Sam/Calendar, then it should render Pages/Calendar.cshtml. If Jessica is logged in and she goes to http://www.example/com/Jessica, then it should render Pages/Home.cshtml.
So basically, ASP.Net Core should look at the URL and compare the username with what's in the database. If the signed in user's username matches the URL, then it should render their home page. If their username does not match the URL then it should continue down the routing pipeline. I don't need help with the database stuff or anything like that. I only need assistance on how to set up the routing.
If all this sounds confusing, then just think of Facebook. It should work exactly like Facebook. If you go to http://www.facebook.com/<your.user.name>, then it brings up your time line. If you go to http://www.facebook.com/<your.user.name>/friends, then it brings up your friends list.
I am basically trying to duplicate that same behavior that Facebook has in ASP.Net Core and Razor Pages. Can someone please provide a simple example or point me to an example? I feel like the way to do this is to use some custom middleware or a custom route attribute, but I am not sure.
You can do something like this. In the Program.cs/startup.cs modify the AddRazorPages like this.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages(options =>
{
options.Conventions.AddPageRoute("/Index", "{user}");
options.Conventions.AddPageRoute("/Calendar", "{user}/calendar");
});
var app = builder.Build();
Now when you access a URL like https://localhost:7131/sam/calendar you will get the calendar page. You can access the user variable like this - #RouteData.Values["user"]
And on the calendar page, you can do something like this.
public class CalendarModel : PageModel
{
public void OnGet()
{
var user = RouteData.Values["user"];
//Query the calendar information from Database.
//If empty redirect the user to the home page or something.
}
}
You can find more details about this here - Razor Pages route and app conventions in ASP.NET Core

Creating dynamic routes in mvc5

Based on my SEO team's recommendation i am trying to generate SEO friendly urls. For some static pages i have done that easily using RouteCollection.MapRoute() like -
//Home/Solutions
routes.MapRoute("Solutions", "Solutions", new { controller = "Home", action = "Solutions" }, new[] { "MyAuction.Controllers" });
//Home/SolutionOfferings
routes.MapRoute("Offerings", "Offerings", new { controller = "Home", action = "SolutionOfferings" }, new[] { "MyAuction.Controllers" });
//Home/Pricing
routes.MapRoute("Pricing", "Pricing", new { controller = "Home", action = "Pricing" }, new[] { "MyAuction.Controllers" });
I was then trying to generate SEO friendly routes for my dynamic routes. For example there are several auctions scheduled for a day which contains hundreds of vehicles scheduled within the auction. To show details of that scheduled vehicle within the auction the actual URL is somewhat -
http://example.com/Auction/VehicleDetails?AuctionId=42&VehicleId=101
Please note that VehicleId represents the Identity within AuctionVehicles table which also contains other details of the vehicle like Make, Model, Year and VIN etc.
What i want to achieve is to generate a dynamic URL like -
http://example.com/42/honda-civic-2010-123456
where 42 is the auction id while honda is the make, civic is the model, 2010 is the year and 123456 is the last 6 digits of the VIN number.
Not sure how to achieve this.
I tried using this link -
Dynamic Routes from database for ASP.NET MVC CMS
Any help would be greatly appreciated.
Routing is one of the most difficult things to grasp in mvc. The best way i have found is MVC attribute routings in ASP.NET MVC 5. (P.s. i'm typing on a phone)
you simply include this line in your RouteConfig
routes.MapMvcAttributeRoutes();
And then you can set optional parameters and default values and map urls in your actual controllers like this:
[Route("books/{bookName?}")]
public ActionResult View(string bookName)
{
if (!String.IsNullOrEmpty(bookName)
{
return View("OneBooks"), GetBooks(bookName));
}
return View("AllBooks"), GetBooks());
}
Your url will look like www.example.com/books/jungle-book
there are many more things you can do. Please read the following article:
https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/
I also found this links and the sublinks on this page to be helpfull to get a proper understanding of mvc routing (lots of reading!!):
https://www.codeproject.com/Articles/641783/Customizing-Routes-in-ASP-NET-MVC
As I said I think attribute routing is your best bet!

ASP.Net Routing in asp.net web-forms

I am using ASP.Net web form Routing for my website but i want to make it more structure & hide all the Querystring ID's with proper Structure like Language/Category/PageName-Title
example: www.abc.com/en/sports/cricket-world-cup
but with my current routing technique i am able to make it work as
www.abc.com/en/1/13/cricket-world-cup
domain/english-folder/language-id/page-id/page-title
How can i make it more structured as `www.abc.com/en/sports/cricket-world-cup
Since i have few Query-string i designed it this way
//For Page.aspx
routes.MapPageRoute("Page_Route", "en/page/{LID}/{PID}/{PageName}", "~/en/Page.aspx", false,
new RouteValueDictionary {
{ "LID", "0"},
{ "PID", "0" },
{ "PageName", "Page-not-found" }},
new RouteValueDictionary {
{ "LID", "[0-9]{1,8}" },
{ "PID", "[0-9]{1,8}" },
});
Result of above Routing get me Friendly URL like this
www.abc.com/en/1/13/cricket-world-cup
But i want to further structure the URL like the one in example.
www.abc.com/en/sports/cricket-world-cup
Example: This url i found is more structure/
http://www.thenational.ae/news/world/europe/turkey-providing-jobs-a-future-for-more-greeks
How can i implement the same structure are they passing querystrings as hiddenfields. Please suggest best approach for such url.
another example is http://mashreqbank.com/uae/en/corporate/lending/trade-finance.aspx
they are using asp.net but i am not sure if it is ASP.Net MVC or ASP.Net webform.
I have been struggling with this kind of routing for quite long and even i cant find a complete example which can take into consideration more than one query-string as most of the example are based on one query-string.
Any help from coding gurus with example would be highly appreciated.
UPDATE:
Let us take this Table into consideration which i use to store page name, title, handler, language regions etc.. This is just a demo table & doesnt resemble the actual website which i am refering to for sample structured url. I am not even sure if they are going it using URL routing or these are actual physical folder & files like old style website where you create actual folder and place files in their etc..
Page_ID Page_Name Page_Title Page_Handler Parent_Page_ID Language_ID Region_ID
1 Home Home index.aspx 0 1 uae
2 Personal Personal index.aspx 0 1 uae
3 Accounts & Deposits Accounts & Deposits index.aspx 2 1 uae
4 Current Account Current Account current-account.aspx 3 1 uae
5 Current Gold Accounts gold Account gold-account.aspx 3 1 uae
6 Easy Saver Easy Saver Account saver-account.aspx 3 1 uae
7 Fixed Deposits Fixed Account fixed-account.aspx 3 1 uae
8 Loans Loans index.aspx 2 1 uae
9 Personal Loans Personal Loans index.aspx 8 1 uae
10 car Loans car Loans car-loan.aspx 8 1 uae
website example for above structure http://mashreqbank.com/
We can use a common page handler if the page design is same this is what i am assuming let us say page.aspx,
Pleae feel to make changes to structure and data inorder to achieve the desired result.
You could simply have something like:
routes.MapPageRoute(
"article-route",
"en/{category}/{pageName}",
"~/en/page.aspx");
And then on en/page.aspx you can access the category and pageName, assuming you have a query to find the correct article based on those two variables:
string category = Page.RouteData.Values["category"] as string;
string pageName = Page.RouteData.Values["pageName"] as string;
Though, if you can't identify a page simply by category and pageName (which seems true per your updated question), you may need the id in the route. In this case, you can ignore the category and pageName route values as they are only there for a nice-looking URL. The only parameter we care about is the id since that is how you identify an article. For example, here are three examples of various routes
routes.MapPageRoute(
"uae-route",
"uae/en/{category}/{id}/{pageName}",
"~/en/index.aspx");
routes.MapPageRoute(
"gbr-route",
"gbr/en/{category}/{id}/{pageName}",
"~/en/index.aspx");
routes.MapPageRoute(
"account-route",
"en/{id}/{pageName}",
"~/en/current-account.aspx");
//then on en/index.aspx and current-account.aspx
int pageId= 0;
if (Int32.TryParse(Page.RouteData.Values["id"] as string, out pageId)) {
// get the page details (including parent page id and language id if needed)
// where Page_ID=pageId.
}
From the sounds of it though, you want to do the first example above, meaning you'll need a way to pull articles by simply category and pageName and not any type of id.
UPDATE: You don't need to create a route for each path... that's the whole point of routing. If you have multiple handlers, then you'll at least need a path for each handler (.aspx page).
It'd be easiest to use an id in the URL, because according to your data structure, that is the only way to identify the page you want to pull. So let's use your example, using these routes:
www.abc.com/en/personal
www.abc.com/en/personal/acounts-deposits/
www.abc.com/en/personal/acounts-deposits/current-account
www.abc.com/en/personal/acounts-deposits/current-gold-account
www.abc.com/en/personal/acounts-deposits/easy-saver
You have one route:
routes.MapPageRoute(
"personal_route",
"en/personal/{category}/{pageName}",
"~/personal.aspx",
false,
new RouteValueDictionary { { "category", string.Empty }, {"pageName", string.Empty}}); //allow for no values
And the personal.aspx has the following code:
protected void Page_Load(object sender, EventArgs e)
{
string category = Page.RouteData.Values["category"] as string;
string pageName = Page.RouteData.Values["pageName"] as string;
if (String.IsNullOrEmpty(category)) {
//no category... must be the /personal route. handle that
}
else if (String.IsNullOrEmpty(pageName)) {
//no page name, just load the category page content
//Psuedo query against your non-existant data schema
//SELECT * FROM SiteContent WHERE Page_Handler='Personal' AND Page_Category=category && Page_URL=""
}
else {
//SELECT * FROM SiteContent WHERE Page_Handler='Personal' AND Page_Category=category && Page_URL=pageName
}
}
As you can see, your problem is you have no way to identify pages without the IDs. You'd need to replace all those IDs in your table with unique URLs. It's doable.

Stackoverflow style URL (customising outgoing URL)

If I navigate to the following stackoverflow URL http://stackoverflow.com/questions/15532493 it is automatically appended with the title of the question like so:
http://stackoverflow.com/questions/15532493/mvc-custom-route-gives-404
That is, I can type the URL into my browser without the question title and it is appended automatically.
How would I go about achieving the same result in my application? (Note: I am aware that the question title doesn't affect the page that is rendered).
I have a controller called Users with an action method called Details. I have the following route defined:
routes.MapRoute("UserRoute",
"Users/{*domain}",
new { controller = "User", action = "Details" },
new { action = "^Details$" });
As this is an intranet application the user is authenticated against their Windows account. I want to append the domain and user name to the URL.
If I generate the URL in the view like so:
#Html.ActionLink("Model.UserName", "Details", "User", new { domain = Model.Identity.Replace("\\", "/") })
I get a URL that look like this:
Domain/Users/ACME/jsmith
However, if the user navigates to the URL Domain/Users/ by using the browsers navigation bar it matches the route and the user is taken to the user details page. I would like to append the ACME/jsmith/ onto the URL in this case.
The research I have done so far indicates I might have to implement a custom route object by deriving from RouteBase and implementing the GetRouteData and GetVirtualPath methods but I do not know where to start with this (the msdn documentaiton is very thin).
So what I would like to know is:
Is there a way of achieving this without implementing a custom route?
If not, does anyone know of any good resources to get me started implementing a custom route?
If a custom route implementation is required, how does it get at the information which presumably has to be loaded from the database? Is it OK to have a service make database calls in a route (which seems wrong to me) or can the information be passed to the route by the MVC framework?
It's actually pretty simple. Since the title is just there for SEO reasons you do not need to get to the actual question, so the Question controller (in SO case) will load the correct question based on the id (in the URL) and redirect the user with a 301 status code.
You can see this behavior with any web inspector
You could do it client-side with Javascript:
history.pushState({}, /* Title Here */, /* URL Here */ );
Only downside is not all browsers support it.

ASP.NET MVC Routing for Master / Detail Views with "Detail Children"

I have the basic Master / Detail Views working great with the default ASP.NET MVC Route; however I would like to build some URLs like this:
/Class/Details/5 -- General Detail view [Working]
What I'm not sure about (and I'm not tied to this URL format, just something roughly equalivent.)
/Class/5/Details/Logs -- Detail View with Logs
/Class/5/Details/Status -- Detail View with current Status
Another way to put this, is like this:
/{controller}/{id}/{controllerSpecificMaster}/{action}/
What I'm trying to avoid, is cluttering up my Views\Class directory with a bunch of Views, which are all basically derivatives of the Details view.
I'm on ASP.NET MVC 1 and .NET 3.5 SP1.
The first thing you need to get down are your routes. You may have already done this, but in case you haven't, here's a route entry that will handle your custom route needs:
routes.MapRoute("Master_Detail",
"{controller}/{id}/{controllerSpecificMaster}/{action}",
new { controller = "Class",
action = "Index",
id = UrlParameter.Optional,
controllerSpecificMaster = "Details"
});
Then, in your action methods where you want to use the route-specified master page, just include the route key in your method arguments, and then pass it to the view:
public ActionResult Logs(int id, string controllerSpecificMaster)
{
//do something
//return view with master name as argument
return View("Logs", controllerSpecificMaster);
}
If you have to do this a lot, I would suggest creating a custom view engine and override the FindView() method.

Categories

Resources