MVC manipulate URL (routing), is it possible? - c#

I have a website that use this pattern.
http://www.domain.com/product/...
My question is now, i need to create a subsite that going to be with this URL pattern, i have tried to change the routing without success.
http://www.domain.com/companyname/product/...
How can i inject the companyname in the URL without breaking my current routing?
Thanks
Niden

Three ways:
If it's relatively static, you can follow Andy's advice in the comments and publish the site in a virtual directory, companyname. Assuming you've properly used the UrlHelper extensions to generate URLs, instead of just hard-coding paths, then everything will just work.
You can create a "companyname" area. The default routing for an area is /area/controller/action. So that would get you the URL structure you want. However, areas are somewhat segregated, so you would need to copy controllers and views to the area's directory. Although, you could subclass controllers from the main app in the area to reuse code.
Just change the default route/add a new route:
routes.MapRoute(
"CompanyDefault",
"{company}/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
// default route here

Related

ActionLink and relative path

I can't find out how to solve this. I have two URLs. These are /my-url-1 and /my-url-2. Both going to different views.
The thing is that I have an ActionLink on /my-url-1's view which should make /my-url-2 and go to that view.
The problem is that ActionLink makes /my-url-1/my-url-2 as the URL and not just /my-url-2.
I was searching two days about how to fix it but couldn't find anything.
PD: I'm not using Areas so please don't tell me that I just should put the "area" parameter as a "".
These are two urls which goes to different controllers and different actions.
View which has the ActionLink (URL:/my-url-1) :
<div class="btn-index-container">
#Html.ActionLink("Url 2", "MyAction", "MyController")
</div>
This ActionLink should render:
Url 2
But it's rendering:
Url 2
where /my-url-1 is my current URL
Route Config
routes.MapRoute(
name: "route1",
url: "my-url-2", //without parameters
defaults: new { controller = "MyController", action = "MyAction" },
);
routes.MapRoute(
name: "route2",
url: "my-url-1", //without parameters too
defaults: new { controller = "MyController2", action = "MyAction2" }
);
So, when I go to localhost:port/my-url-1 it loads MyAction2 which renders a view. This view has inside an ActionLink(described above) which should render a /my-url-2 link.
Well, I've worked inside the MVC framework and I could told you about how Url.RouteUrl or Html.RouteLink works. At the end, the method which create the URL is GetVirtualPathForArea (this method is called before UrlUtil.GenerateClientUrl, which receive the VirtualPathData.cs created by GetVirtualPathForArea, as a parameter) from System.Web.Routing.RouteCollection.cs.
Here I left a link to the MVC source code:
https://github.com/aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc
I found that, my Request.ApplicationPath was changing when I loaded /my-url-1. It was crazy because the application path was /.
At last, the problem was that the /my-url-1 was pointing to a virtual directory created on the IIS some time ago by error.
To know where your IIS configuration file is, please follow the link below:
remove virtual directory in IIS Express created in error
The solution was remove the .vs directory (which contains the config .vs\config\applicationhost.config) and rebuild
I think most of the Helpers that render URLs works more or less in the same way, so I hope it'll useful for all of you!
In your case, maybe no its necesary, just pass the parameters with null values, E.G.
#Html.ActionLink("Español", null, null, new { Lng = "es" }, null)
In this way, the parameters change, and the view is relative, depending on where you are.

ASP.NET MVC map single controller to root of website

I am working on an ASP.NET MVC 5 website that has a public "marketing" website that contains somewhat static pages with information about the company, legal, social, contact us, etc. that a non-logged in user can access. Then, once logged in, there is a back end of the website that registered users have access to features.
Originally I had all the public "marketing" pages going to http://www.mywebsite.com/Marketing/About, http://www.mywebsite.com/Marketing/Social, etc.
However, the business wants all the "marketing" pages, to be accessible a single directory down from the root website, so the links above would be accessible with:
http://www.mywebsite.com/About, http://www.mywebsite.com/Social, etc.
I know I can use the below approach to get it to work by registering individual routes for each "marketing" page like so:
routes.MapRoute(
"ShortAbout",
"About",
new { controller = "Marketing", action = "About" }
);
routes.MapRoute(
"ShortSocial",
"Social",
new { controller = "Marketing", action = "Social" }
);
However, since there are about 15 "marketing" pages, this seems inefficient and it seems like there must be a better way to do this.
I also tried a generic routing approach outlined here: http://www.wduffy.co.uk/blog/aspnet-mvc-root-urls-with-generic-routing/
but the problem with that approach was I had a "marketing" page, with the same name as a controller and it ended up forwarding the user to the marketing subdirectory. For example, I had a Controller called "MachineController", and in the "MarketingController" I had an action/page called "Machine", so it was forwarding the user to /Marketing/Machine using the approach in the above link.
Any other ideas? Thanks in advance.
I had exactly this problem. A much simpler but more hardcoded solution is
routes.MapRoute("MarketingPages", "{action}",
new { controller = "Marketing" },
new { action = #"About|Social" });
The last anonymous object constrains the route to match routes where action matches the supplied regular expression, which is simply a list of the urls you want to have marketing pages. Any other url like '/something' falls through to the routes below.

How to ignore all characters after "controller/action" in an ASP.NET MVC route?

I would like my ASP.NET MVC4 application to only serve the base HTML markup for a specific page, and after that I'm processing everything else on client-side with knockout.js/history.js/AJAX, including the initial page load.
So when someone refers to URL http://example.com/products/list/food/fruits, the MVC router should simply ignore everything what is behind "products/list" and route the request to ProductsController and List action. Then on client-side I will handle the rest and load the requested data accordingly.
I was playing with the route definitions, I tried to completely skip the "products/list" route, I also tried to add a "products/list/*" route, but didn't have success yet.
You can use an asterisk as part of the last variable in a route. For example, when configuring your routes:
routes.MapRoute(
"ProductRoute",
"products/list/{*otherArgs}",
new { controller = "Products", action = "List" });
You can learn more in MSDN's Documentation on routing under the section "Handling a Variable Number of Segments in a URL Pattern"
You will need to create your own route.
Something like this should do the trick:
routes.MapRoute("Products", "Products/{List}",
new {controller = "Products", action = "List"}
);
Note: I´m not sure if the other parameters are required in the route.

Deploying MVC Area as a self standing web site

I have an MVC Application with multiple Areas. They share a lot of common code and components, so I do not want to break them up into separate Projects. But I would like to deploy them to separate web sites.
The normal routing is:
www.mysharedsite.com/Area1
www.mysharedsite.com/Area2
...
But I would like to deploy them as:
www.area1site.com/
www.area2site.com/
...
I was thinking of putting a field in the web.config and then adding logic in the RouteConfig and the RegisterAreas of each area to change the Routes and turn off Routes to Controllers altogether. But this seems kludgy.
Is there a clean way of doing this?
What I would do is create and install a custom ActionInvoker which reads the hostname from the request, and based on it, sets the appropriate Area path for you:
protected override ActionResult InvokeActionMethod(...)
{
// Get hostname
var hostname = controllerContext.HttpContext.Request.Url.Host;
if (hostname == "some value you want")
{
controllerContext.RouteData.DataTokens["area"] = "your area here";
}
return base.InvokeActionMethod(controllerContext, actionDescriptor, parameters);
}
You could specify a route based on the hostname, mapping it to an area. Based on the URL format in your question:
routes.Add("DomainRoute", new DomainRoute(
"{area}site.com", // Domain with parameters
"{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
));
See this post for the DomainRoute class:
http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx
Why not put the common code in a seperate dll
and link your websites to this dll?
Your solution will be a lot bigger if you add another website that also shares the common code.

Asp.net MVC2 URL structure - best practices

What are the best practices for setting up projects with multiple interfaces in asp.net MVC2? I'm starting a project where we need a typical arrangement like:
example.com/ - end-user interface
example.com/Admin/ - site management
The site will be involved enough that simply having all the user logic in HomeController and all the admin logic in AdminController isn't really an option. I've read about using multiple Route definitions, but the following doesn't seem to work properly:
routes.MapRoute(
"Admin", // Route name
"Admin/{controller}/{action}/{id}", // URL with parameters
new { controller = "Admin", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
It causes all the links on the homepage to point to example.com/Admin/local-part instead of example.com/local-part.
I'd like to avoid specifying a different MapRoute for each Admin controller (omitting {controller} from the mapping each time).
I've also read about setting up different Areas within a project, but that seems like it would be too involved for the scope of this project.
Finally, I've also read that you can put constraints on MapRoutes, but the documentation on that part seems confusing to me. Is there something obvious I'm missing? Failing that, are there any best practices for asp.net structure that I should keep in mind?
It sounds like Area's is ready made for what you want to do. Setting up an area isn't really all that involved, basically you just have to register it. By default the area routing will match the default in the global.asax, the exception being the extra "\area" slug in the url. I'm fairly certain it only took me a few minutes when I set this up on a project a few months ago.
If your Admin controller is complicated enough to exceed the scope of a single controller then that indicates that an area may be warranted.

Categories