ASP.NET MVC unique url routing - asp.net-mvc

So, I've read through tutorials and books about MVC routing as well as played with it on my projects and come to a pretty solid understanding of how to use it to accomplish what I want to with it.
But, I'm up against something I can't quite figure out yet.
What I want to accomplish is a unique url for each client that doesn't look like "http://mysite.com/client/1". This url would take the browser to the Client Controller, Index action, ClientId = 1...obviously.
What I'd like to do is have a URL like "http://mysite.com/Acme" that would do a database lookup to figure out which client has the unique name of "Acme", and then redirect the request to the Client Controller, Index view and set the ClientId to whatever it is on the client with the name 'Acme'.
The default route keeps catching it and can't handle it.
Any ideas?

I recommend using an Global Action Filter to accomplish this or you can create a route with a static path that will route to your lookup controller (e.g., /lookup/{companyname} will route to your database lookup controller).

How about "http://www.mysite.com/Clients/{ClientName}"
routes.MapRoute(null, "Clients/{ClientName}", new{controller = "Clients", action = "Index"};
public class ClientsController : Controller
{
public ActionResult Index(string clientName)
{
var id = Db.GetClientIdBy(clientName);
// do your redirect...
}
}
Or have I missed the point?

Related

How to rewrite MVC 5 routes?

I have two question about generating routes in MVC 5.
This is example:
routes.MapRoute(
name: "ActionSite",
url: "{userName}/sites/{action}/{localSiteName}",
defaults: new { controller = "Site" }
);
#Url.RouteUrl("ActionSite", new { action="Edit", siteOrder = site.Order, localSiteName = site.LocalName, userName = ViewBag.UserName })
generates the next url:
https://localhost:44344/TestUser/sites/Edit/Site2?siteOrder=1
1)How to hide variables? I want to hide: ?siteOrder=1
2)TestUser is userName. At this moment I set manually it in all [Authorize] actions. Can I do this one time in some special method?
About first question, RouteUrl assumes you are going to use the URL in a GET method and when you are using GET verb you have to append query string to the URL. siteOrder has to be in query because you did not put it into URL template. Any extra parameter goes into query string.
Solution here is to use POST instead of GET. Down side would be losing simple GET calls ( anchor) from client side. You have to use #Html.BeginForm instead of #Html.ActionLink.
Second question is not clear, if you generate URL like https://localhost:44344/TestUser/sites/Edit/Site2?siteOrder=1 then you will get username form URL.
for example:
public ActionResult Edit(string userName, string localSiteName){ }
username here will be "TestUser" and you have to check authentication if userName is same as User.Identity.GetUserName()
Or you can write AuthenticationFilter to do the authentication job for you.
But if you mean a way that Url.RouteUrl automatically fill in userName property based on User.Identity I think answer is no. You have to retrieve username somewhere in ActionFilters or in Action or if you are using ASP.Identity then you already have the user name all the way down to the View, just you need to call
#User.Identity.GetUserName()
in your View or Controller to get it.

ASP.NET MVC Dynamic Action with Hyphens

I am working on an ASP.NET MVC project. I need to be able to map a route such as this:
http://www.mysite.com/Products/Tennis-Shoes
Where the "Action" part of the URL (Tennis-Shoes") could be one of a list of possibilities. I do not want to have to create a separate Action method in my controller for each. I want to map them all to one Action method and I will handle the View that is displayed from there.
I have this working fine by adding a route mapping. However, there are some "Actions" that will need to have a hyphen in them. ASP.NET MVC routing is trying to parse that hyphen before I can send it to my action. I have tried to create my own custom Route Handler, but it's never even called. Once I had a hyphen, all routes are ignored, even my custom one.
Any suggestions? Details about the hyphen situation? Thanks you.
Looking at the URL and reading your description, Tennis-Shoes in your example doesn't sound like it should be an action, but a Route parameter. Let's say we have the following controller
public class ProductsController : Controller
{
public ActionResult Details(string product)
{
// do something interesting based on product...
return View(product);
}
}
The Details action is going to handle any URLs along the lines of
http://www.mysite.com/Products/{product}
using the following route
routes.MapRoute(
null,
"Products/{product}",
new
{
controller = "Products",
action = "Details"
});
You might decide to use a different View based on the product string, but this is just a basic example.

Asp mvc redirect without affecting url

I have a rather archaic login system, and this is part of the login action:
// login action
return RedirectToAction("Action", new {
id = aVal,
name = aName,
// other params
});
It redirects the user to the Action action, and i noticed that name and the other params ended up being part of the final url scheme. I need to pass all those values to Action.
[HttpGet]
public ActionResult Action(int id, string name, ...) {
Is it possible to pass them to Action and having the url like this: /Controller/Action/123.
I need to restrict the Action method to only those who pass through the login action, the long url + query string make it almost impossible to make it through, but is there another more profesional way to do it.
Thanks and greetings to the SO and SE community.
In order to get Restful styled url's you need to setup an appropriate route.
So in your case something like
routes.MapRoute("MyRoute", "MyController/MyAction/{id}/{name}", new { controller = "MyController", action = "MyAction" });
you can see some other examples here
The second part of your question is more vague - you may want to tag your class with an [Authorize] attribute and then override OnAuthorization where you can do any checks. Not sure if this is what you are looking for.
There is an example of this here

Should a PUT identifier come from the URL or from the HTTP request data?

This question is probably a dupe, but I couldn't find a similar one (not sure exactly what to search for).
Say I have a restful resource URL like this:
/my/items/6/edit
There is a form at this page which allows me to edit my #6 item. When I submit the form, it POSTS to /my/items/6, with a PUT X-HTTP-Method-Override header.
My question is, where should the server handler get the value "6" from? Should it get it from the URL? Or from the HTTP POST data (say the id was rendered as a hidden input field on the form)?
It seems to me like it should come from the URL. However this makes it a little more trouble to get it out. For example in .NET MVC, you might get it like this from a controller action method:
var id = int.Parse(ControllerContext.RouteData.Values["id"].ToString());
...which seems like more trouble than it's worth. However, if we get it out of the HTTP POST data, then technically you could post/put data for my item #6 to /my/items/7, and the server would still save the item data under id #6.
Are there any standard practices here?
Check this: http://www.codeproject.com/Articles/190267/Controllers-and-Routers-in-ASP-NET-MVC-3
I'm not a .net developer, though best practice in all platforms is to map your URI template to controller. Router must parse and prepare such information and pass it to your function/method.
It should definitely come from the URL. In ASP.NET MVC, if you had a route defined like this:
routes.MapRoute(
"Default",
"/my/{controller}/{id}/{action}",
new { controller = "items", action = "Index" }
);
You would be able to reference the ID from the ActionResult method signature, like this:
[HttpPut]
public ActionResult Index(int id, MyItemEditModel model)
{
// id would be 6 if the URL was /my/items/6/
// and the model need not contain the id
...

URLs the asp.net mvc way

In the conventional website a url displayed as:
http://www.mySite.com/Topics
would typically mean a page sits in a subfolder below root named 'Topics' and have a page named default.htm (or similar).
I'm trying to get my head in gear with the MVC way of doing things and understand just enough of routing to know i should be thinking of URLs differently.
So if i have a db-driven page that i'd typically script in a physical page located at /Topics/index.aspx - how does this look in an MVC app?
mny thx
--steve...
It sounds like you are used to breaking down your website in terms of resources(topics, users etc) to structure your site. This is good, because now you can more or less think in terms of controllers rather than folders.
Let's say you have a structure like this in WebForms ASP.NET.
-Topics
-index.aspx
-newtopic.aspx
-topicdetails.aspx
-Users
-index.aspx
-newuser.aspx
-userdetails.aspx
The structure in an MVC app will be pretty much the same from a users point of view, but instead of mapping a url to a folder, you map a url to a controller. Instead of the folder(resource) having files inside it, it has actions.
-TopicController
-index
-new
-details
-UserController
-index
-new
-details
Each one of these Actions will then decide what view (be this html, or json/xml) needs to be returned to the browser.
Actions can act differently depending on what HTTP verb they're repsonding to. For example;
public class UserController : Controller
{
public ActionResult Create()
{
return View(new User());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(User user)
{
// code to validate /save user
if (notValid)
return new View(user);
else
return new View("UserCreatedConfirmation");
}
}
This is sort of a boiled down version of RESTful URLs, which I recommend you take a look at. They can help simplify the design of your application.
It looks just like you want it to be.
Routing enables URL to be quite virtual. In asp.net mvc it will end at specified controller action method which will decide what to do further (i.e. - it can return specified view wherever it's physical location is, it can return plain text, it can return something serialized in JSON/XML).
Here are some external links:
URL routing introduction by ScottGu
ASP.NET MVC tutorials by Stephan Walther
You would have an default view that is associated with an action on the Topics controller.
For example, a list page (list.aspx) with the other views that is tied to the list action of the Topics controller.
That is assuming the default routing engine rules, which you can change.
Read more here:
http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
IMHO this is what you need for your routes.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Topics", action = "Index", id = "" } // Parameter defaults
);
You would need a TopicsController that you build the View (topics) on.

Resources