ASP NET Custom Routing - asp.net
I have following patterns
/invitation/mission/busstop -- return the list of busstops
/invitation/mission/busstop/id -- return a specific busstop
/invitation/mission/driver -- return the list of drivers
/invitation/mission/driver/id -- return a specific driver
/invitation/mission/driver/city/model/limit -- query driver accoring to city, model and age limit
...
/invitation/questionair -- return the list of questionairs
/invitation/questionair/id -- return a specific questionair
/invitation/questionair/create -- create a new questionair
/invitation/questionair/update/id -- update a questionair
...
I expect the 'invitation' to be controller, and the rest to be action. Each of the above url should corresponds to a dedicated view page.
Can anyone help me to design the routes?
=====================================================================
I update the patterns, and add my expectation at the end of each url. Any suggest on the url patterns?
Here is the answer to keep your controller simple and still having good url patterns:
Controller:
public class InvitationController : Controller
{
public ActionResult GetAllBusStops()
{
//Logic to show all bus stops
//return bus stops
return View();
}
public ActionResult GetBusStopById(string id) //Assumed your id to be a string
{
//Logic to get specific bus stop
//return bus stop
return View();
}
public ActionResult GetAllDrivers()
{
//Logic for driver list
//return driver list
return View();
}
public ActionResult GetDriverById(int id) //Assumed your id to be an integer
{
//Logic to get specific driver
//return driver
return View();
}
public ActionResult GetDriver(string city, string model,int limit) //Assumed datatypes
{
//Logic to get specific driver with this criteria
//return driver
return View();
}
public ActionResult GetAllQuestionairs()
{
//Logic for questionair list
//return the list
return View();
}
public ActionResult GetQuestionairById(int id) //Assumed your id to be an integer
{
//Logic to get specific questionair
//return it
return View();
}
public ActionResult CreateQuestionair(QuestionairCreateModel model)
{
//logic to create questionair
return View();
}
public ActionResult GetQuestionairById(int id) //Assumed your id to be an integer
{
//Logic to get specific questionair
//return it
return View();
}
public ActionResult UpdateQuestionairById(int id) //Assumed your id to be an integer
{
//Logic to update specific questionair
//return it
return View();
}
}
Now go to your App_Start Folder, Open RouteConfig.cs, start adding the REST urls in the routes as below:
routes.MapRoute(
"List Bus Stops", // Route name
"invitation/mission/busstop", // No parameters for Getting bus stop list
new { controller = "Invitation", action = "GetAllBusStops"}, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Get Bus stop by id", // Route name
"invitation/mission/busstop/{id}", // URL with parameters
new { controller = "Invitation", action = "GetBusStopById" }, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Get All Drivers", // Route name
"invitation/mission/driver", // No parameters for Getting driver list
new { controller = "Invitation", action = "GetAllDrivers"}, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Get Driver by id", // Route name
"invitation/mission/driver/{id}", // URL with parameters
new { controller = "Invitation", action = "GetDriverById" }, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Get driver for city, model, limit", // Route name
"invitation/mission/driver/{city}}/{model}/{limit}", // URL with parameters
new { controller = "invitation", action = "GetDriver"}, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Get All Questionairs", // Route name
"invitation/questionair", // No parameters for Getting questionair list
new { controller = "Invitation", action = "GetAllQuestionairs"}, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Get questionair by id", // Route name
"invitation/questionair/{id}", // URL with parameters
new { controller = "Invitation", action = "GetQuestionairById" }, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET") }
);
routes.MapRoute(
"Create New Questionair, // Route name
"invitation/questionair/create", // URL with parameters
new { controller = "invitation", action = "CreateQuestionair" }, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("POST") }
);
routes.MapRoute(
"Update Questionair, // Route name
"invitation/questionair/update/{id}", // URL with parameters
new { controller = "invitation", action = "UpdateQuestionairById" }, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("POST") }
);
Many things are assumed like the datatypes and model names. You can figure out how it works from this....
Add the route in the global.asax
routes.MapRoute(
"Default",
"{controller}/{id}",
new { controller = "invitation", action = "Index" }
);
Then in your controller use something like:
public class InvitationController : Controller
{
public ActionResult Index(string id)
{
switch(id.ToLower())
{
case "mission/busstop/list":
return View("busstop/list");
case "mission/driver/query":
return View("driver/query");
}
//Return default view
return View();
}
}
The other answers are valid, but I think there is a much easier, cleaner, and more maintainable way of defining your routes: use an attribute-based route mapper.
The easiest one I've found to use is the RiaLibrary.Web route mapper. All you have to do is add an attribute on each method you want to have a route for - then specify your route details.
To get set up, you must follow a few steps outlined on the RiaLibrary.Web page. After completing those steps, you can change any Controller action to look like this:
[Url("Articles/{id}")]
public ActionResult Details(int id)
{
// process
return View();
}
If you have any optional parameters, declare them as {param?} in the route string and then as int? param in your method declaration.
That's it! You can also include some other parameters to specify whether only certain types of HTTP calls match this route, to define constraints on parameters, and to fix the order in which this route is matched.
Related
ASP.NET MVC5 Routing Error : works for one Action but not for the other
I have 3 actions; category, tag and search that has the same type of route signature but the routes start with different values. Now only the category is working fine but the other two aren't. Search action shows : localhost/search?s=SOMEWORD in the url and page loads. But tag action gives me an error: The resource you are looking for has been removed, had its name changed, or is temporarily unavailable. I wanted my routes to be localhost/{action}/{someWord} but could not. Controller Actions: public ActionResult Category(string category, int p = 1) { //some caculations return View("List", viewModel); } public ActionResult Tag(string tag, int p = 1) { //some caculations return View("List", viewModel); } public ActionResult Search(string s, int p = 1) { //some caculations return View("List", viewModel); } RouteConfig: routes.MapRoute( "Category", "Category/{category}", new { controller = "Blog", action = "Category" } ); routes.MapRoute( "Tag", "Tag/{tag}", new { controller = "Blog", action = "Tag" } ); routes.MapRoute( "Search", "Search/{s}", new { controller = "Blog", action = "Search" } );
Custom routing and RedirectToAction doesn't work
Action: public virtual ActionResult Index(string msg, int id) { ViewBag.Message = msg; ViewBag.BookingOfficeGroupId = id; return View(); } Controller Name: UserController RouteConfig: routes.MapRoute( "UserPro", // Route name "UserPro/{action}/{msg}/{id}", // URL with parameters new { controller = "User" } // Parameter defaults ); it works fine when I input url directly as http://localhost:83331/UserPro/Index/ssssss/0 but doesn't work with RedirectToAction return RedirectToAction("Index", "UserPro" , new { msg = "Welcome" , id= 0 }); It gives me error resource not found. Where I am mistaken? Edit I just tried this url in browser and it doesn't work. Gives same error http://localhost:83331/UserPro/Index?msg=Welcome&id=1
MVC Action Method with nullable parameter
I am calling a action with the parameter value. But it is not assigning parameter value to action method parameter. public ActionResult UserDetail(long? userId) { } localhost/Admin/UserDetail/10 --> 10 is not passed to userId But localhost/Admin/UserDetail/?userId=10 --> This works What causes the first url not working? Any help? Update: tried this in global.asax still not working routes.MapRoute("ExistSiteUser", "UserDetail/{userId}", new { controller = "Admin", action = "UserDetail", // nothing optional } ); routes.MapRoute("NewSiteUser", "UserDetail", new { controller = "Admin", action = "UserDetail", userId = UrlParameter.Optional } );
change the parameter name to 'id' instead of 'userid' and then try....it should work then public ActionResult UserDetail(long? id) { }
Replace this userID to id :- public ActionResult UserDetail(long? id) { }
asp.net mvc routing id parameter
I am working on a website in asp.net mvc. I have a route routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); which is the default route. And I have a method public ActionResult ErrorPage(int errorno) { return View(); } Now if I want to run this code with http://something/mycontroller/Errorpage/1 it doesn't work. But if I change the parameter name to id from errorno it works. Is it compulsory to have same parameter name for this method? Or do I need to create separate routes for such situations?
So, you have a parameter named errorno, and you want it to have a value from parameter id. This is obviously the binding problem. How to solve it: create a class for model binder: public class ParameterBinder : IModelBinder { public string ActualParameter { get; private set; } public ParameterBinder(string actualParameter) { this.ActualParameter = actualParameter; } public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { object id = controllerContext.RouteData.Values[this.ActualParameter]; return id; } } create a custom attribute for custom model binding: [AttributeUsage(AttributeTargets.Parameter)] public class BindParameterAttribute : CustomModelBinderAttribute { public string ActualParameter { get; private set; } public BindParameterAttribute(string actualParameter) { this.ActualParameter = actualParameter; } public override IModelBinder GetBinder() { return new ParameterBinder(this.ActualParameter); } } apply the new attribute to your action parameters as needed: public ActionResult ErrorPage( [BindParameter("id")] int errorno) { return View(); } Now your errorno will have the value, which was passed as id for your url. Note: you can remove the paramter id from the example above, if you are sure you need it solved only for id. Leaving this way will allow you bind other parameters too.
Option 1 routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); public ActionResult ErrorPage(int id) { return View(); } Option 2 routes.MapRoute( "Default", "{controller}/{action}/{errorno}", new { controller = "Home", action = "Index", errorno = UrlParameter.Optional } ); public ActionResult ErrorPage(int errorno) { return View(); } Option 3 routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); public ActionResult ErrorPage(int id) { int errorno = id; return View(); }
use the bind attribute prefix: public ActionResult Customer([Bind(Prefix = "id")]string cname) {}
#Parminder The default route can handle all action with one parameter "id". And I think not every action need this parameter. So I change my default route routes.MapRoute( "Default", "{controller}/{action}", new { controller = "Home", action = "Index"} ); and you can add a new route: routes.MapRoute("errorpage", "yourcontroller/errorpage/{errorno}", new {controller="controllername", action="errorpage"}); this just handle your controll name is "controllername". If you want to handle all controller, you can add this: routes.MapRoute("errorpage", "{controller}/errorpage/{errorno}", new {controller="controllername", action="errorpage"}); This method will create very much code in global.asax if you need a lot of custom route.
You could either rename the parameter in the default root (which probably is not a good idea) or rename it in the action method. Adding another root will not help because it will be the same as the default one and given an url the routing engine cannot distinguish between the two and will always take the first one in the list.
try to use the same name of parameter in action method as in in the route table url parameter. global.asx routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); myController public ActionResult ErrorPage(int id) { return View(); }
How do you write a get method that retrieves the title of an object, not its Id - w/ ASP.NET MVC
So this is the method in my repository I use to get records from my db via its Id public BlogsTable GetBlogPosts(int id) { return db.BlogsTables.SingleOrDefault(d => d.Id == id); } And this is my controller using the get method public ActionResult Details(int id) { BlogsTable blogPostDetails = repo.GetBlogPosts(id); return View(blogPostDetails); } What I need is to be able to write a get method that allows me to get records from my db by the title, instead of its id. This is what I have now Also, how to I set the route to use that method? This is what I have now routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Blog", action = "Index", id = "" } );
public BlogsTable GetBlogPostsByTitle(string title) { return db.BlogsTables.SingleOrDefault(d => d.Title == title); } public ActionResult Details(string id) { BlogsTable blogPostDetails = repo.GetBlogPostsByTitle(id); return View(blogPostDetails); }