rout registration breaks when I change the url in global.asax - c#

The following rout registration works for my asp.net MVC application
routes.MapRoute("TrackingChannels", "TrackingChannels/{action}",
new { controller = "TrackingChannels", action = "Index" });
When I change it to catch this url,
I get resource not found error
for localhost:85\dis\TrackingChannels
routes.MapRoute("TrackingChannels", "Dis/TrackingChannels/{action}",
new { controller = "TrackingChannels", action = "Index" });
How can I fix this?

Alright, I need to go out so I'll post this now as I don't know how long I'll be.
I setup a default MVC 3 project and changed the routing to match your case.
Global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"TrackingChannels",
"Dis/TrackingChannels/{action}",
new { controller = "TrackingChannels", action = "Index" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Added a TrackingChannelsController:
public class TrackingChannelsController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Test()
{
return View();
}
}
I deliberately added the Test action to see if /dis/trackingchannels/{action} would also work. Then I added a couple of views which resulted in the following project structure:
Finally, here's the results of specifying the URLs in the browser:
First with /dis/trackingchannels:
Second with /dis/trackingchannels/test:
The only thing I can say without seeing your project is to double check the URL is matching the correct route. To do that you can use Phil Haack's RouteDebugger.

Related

ASP MVC 1 Custom Routing for Folders and SubFolders

I'm developing a simple CRUD application using ASP MVC 1 that will store data across multiple tables for multiple student programs. In doing so, I'm trying to figure out how to structure the URL to accommodate each program, their tables, and their actions.
For example, something I am trying to achieve is:
site.com/StudProg1/Participant/Create will be the URL for inserting an entry for the Participant Table for Student Program 1
site.com/StudProg2/Course/ will be the URL for the Index page for the Course Table for Student Program 2
In my attempt to create custom routes to accommodate this, my Global.asax.cs file stands as follows:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"StudProg1",
"StudProg1/{pageName}/{action}",
new { controller = "StudProg1", pageName="Index", action = "Index" }
);
routes.MapRoute(
"StudProg2",
"StudProg2/{pageName}/{action}",
new { controller = "StudProg2", pageName="Index", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
}
Where pageName is supposed to be the table name.
Not surprisingly, the above structure does not return the output I am aiming for (i.e. it always points to the Index page for StudProg).
Additionally, my file directory is structured as such:
Views
StudProg1
Index
Participant
Index
Create
StudProg2
Index
Courses
Index
Create
etc.
My question is, how can I improve my routes to correctly achieve the URL structure I desire. Additionally, besides the Microsoft ASP.NET Developer Network Site, are there any good tutorials on custom routes?
You should not be creating a controller for each student program (StudProg1,StudProg2 etc). You can accept that as a parameter.
You need only 2 controlellers, one for Particiant and one for Course.
public class ParticipantController : Controller
{
public ActionResult Index()
{
return Content("Reques for partiicpant index page if needed");
}
public ActionResult create(string studentProgram)
{
return Content("Partiicpant create for "+studentProgram);
}
}
public class CourseController : Controller
{
public ActionResult Index()
{
return Content("Course:");
}
}
and in your RouteConfig's RegisterRoutes method, specify the 2 specific routes before the generic default route.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("part","{studentProgram}/Participant/{action}",
new { controller = "Participant", action = "Index" }
);
routes.MapRoute("course", "{studentProgram}/Course/{action}",
new { controller = "Course", action = "Index" }
);
routes.MapRoute("Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}

C# MVC Redirect a dynamically specified route to a fixed action

I am using C# MVC.
I have an action which looks like this.
public class CustomController : Controller
{
public ActionResult CustomPage(int customPageId)
{
var model = new CustomPageViewModel()
{
customPageId = customPageId
};
return View(model);
}
}
I want to be able to hit this action but to use a different route. For example I want Home/Index to actually hit this action, but to report in the URL that its Home/Index.
My custom pages are stored in the database which tell it what route to have, how can I create routes for my pages programatically and have MVC perform the required actions?
As this is a CMS based system, I don't want to have to create a Home/Index controller and action, as the user may choose any route they wish.
Thanks, Tom
FYI: I have sort of figured this out. Unfortunately Routes are defined when the application starts, so I have to force a restart if I want to setup a new route while the app is running...
Here is the code I have used to setup my routes incase it helps anybody else.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var pageList = new PageService().Get();
foreach (var page in pageList)
{
var targetRoute = string.Format("{1}/{2}", page.PageArea, page.PageController, page.PageAction);
if (!string.IsNullOrWhiteSpace(page.PageArea))
targetRoute = string.Format("{0}/{1}/{2}", page.PageArea, page.PageController, page.PageAction);
routes.MapRoute(
string.Format("PageBuilder_{0}", page.PageId),
targetRoute,
new { area = "Builder", controller = "Build", action = "Index", pageId = page.PageId }
);
}
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

How to Create a dynamic Controller to handle many static Views in ASP.NET MVC?

I have a bunch of mostly-static pages (about 40),
like: order-form01.html, order-form02.html, orderform03.html etc..
Should each of them have its own Controller/Action, or is that possible to have one dynamic Controller/Action for all of them?
My Url should look like this: http://MyProject/GlobalController/IndividualView and for the above example: http://MyProject/OrderForm/order-form01, http://MyProject/OrderForm/order-form02 etc..
Thanks in advance.
Yes it's very easy AND you don't need a switch statement or any other redundant logic.
public class MyController
{
public ActionResult Page(string file)
{
return View(file);
}
}
The magic is in the Route Map:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// New MapRoute for your 40+ files..
routes.MapRoute(
"OrdeForm",
"OrderForm/{file}",
new { controller = "MyController", action = "Page", {file} = "" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
Additionally:
I pass the View name in the query string.
Is not required, but is supported. The following urls will work:
// Url Parameters
http://MyProject/OrderForm/order-form01
http://MyProject/OrderForm/order-form02
// Querystring Parameters
http://MyProject/OrderForm?file=order-form01
http://MyProject/OrderForm?file=order-form02
The only catch is that you need to rename your html files to cshtml and place them in the correct directory for the ViewEngine to find.
#Erik, I also bit of new to mvc . Could you please explain your route map as of how is it possible with default raute again and again
Routes are broken down into 3 values:
Controller
Action
Parameter(s)
At a bare minimum, the controller and action are required. Where the values come from is not dependent on the Url. For example, in the following Url and Map Route...
// Url
http://MyProject/
// MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = "" }
);
// Controller named "Home" matches the default in the above route
// Method named "Index" matches the default in the above route
public class HomeController {
public ActionResult Index() {
return new EmptyResult();
}
}
... everything still works because we provided a default value for the controller and action.
Ok let's break down the URL you want:
http://MyProject/OrderForm/order-form01
http://MyProject/OrderForm/order-form02
http://MyProject/<identifier>/{parameter}
You have one identifier that tells me route (OrderForm) and one changing value that because it changes and you want one value, should be a parameter.
http://MyProject/<identifier>/{file}
The name of the parameter makes no difference as long as it matches the signature of the controller method:
http://MyProject/{Controller}/{file}
public class HomeController {
public ActionResult Index(string file) {
return new EmptyResult();
}
}
or
http://MyProject/{Controller}/{einstein}
public class HomeController {
public ActionResult Index(string einstein) {
return new EmptyResult();
}
}
I named the parameter file, because it tells me it's the parameter is a name of a file, whereas the name einstein has no inherent description so is a terrible name for a variable.
http://MyProject/{Controller}/{file}
// MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = "" }
);
// Controller named "Home" matches the default in the above route
// Method named "Index" matches the default in the above route
public class HomeController {
public ActionResult Index() {
return new EmptyResult();
}
}
Now we only want this route to run when the identifier is OrderForm so we don't allow that to be a value, we hard code it.
url: "OrderForm/...
Next we have a value that keeps changing, so we to add url parameter:
url: "OrderForm/{file}"
Now we have an issue because we aren't allowing MVC to parse values from the url to populate Controller nor Action so we must supply them.
routes.MapRoute(
name: "",
url: "OrderForm/{file}",
defaults: new { controller = "Home", action = "Index", file = "" }
);
Here we've mapped the url http://MyProject/OrderForm/{file} to:
public class HomeController {
public ActionResult Index(string file) {
return new EmptyResult();
}
}
Now I would choose to to update the defaults to something more specific and descriptive:
routes.MapRoute(
name: "",
url: "OrderForm/{file}",
defaults: new { controller = "OrderForm", action = "Index", file = "" }
);
public class OrderFormController {
public ActionResult Index(string file) {
return new EmptyResult();
}
}
Hope that all makes sense.
After the question edited :my solution is, you can have one controller/action and it should call view (cshtml). Your querystring data should be pass to view as of viewbag variable and partial views should be called acording to the viewbag variable. noo need of editing routing table even(if you are willing to pass it as a query string).
//your routeconfig will be
routes.MapRoute(
name: "default",
url: "{controller}/{file}",
defaults: new { controller = "OrderForm", action = "Index", file = "" }
);
//here no need to have 40 routing table one is enough
//your controller/action will be
public class OrderForm
{
public ActionResult Index(string file)
{
ViewBag.Orderform=file
return View(file);
}
}
//view bag variable is accessible in view as well as in javascript
But I would say as best practice, you can modify default routing to access all urls and navigate it to same controller/action and let that action to return the view. After that use angular / knockout js to handle client side routing and based on it the partial views should be loaded.(still your url will be different for your 40 pages but noo need to pass it as query string)
//your route table will be
routes.MapRoute(
name: "default",
url: "{controller}/{file}",
defaults: new { controller = "OrderForm", action = "Index"}
);
//your controller will be
public class OrderForm
{
public ActionResult Index()
{
return View(file);
}
Navigation should be handled by client side routing

MVC to web form redirection without changing URL

my requirement is, there will be one controller method, which will handle all the request, that might return MVCview/model, or it might return .ASPX page, in any case URL must be same.
something like following.
public ActionResult HandleRequest()
{
if(Module is Converted)
{
return view(ModuleName);
}
else
{
//return module.aspx page, Here I can user Redirect method but it will change URL
//I don't want browser's Url to be changed.
}
}
Your answer is Routing.
http://msdn.microsoft.com/en-us/library/cc668201.aspx
Look at following code :
public ActionResult Test()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return RedirectToAction("TestAspx");
}
public ActionResult TestAspx()
{
ViewBag.Message = "Your app Test aspx page.";
return View();
}
Here the action TestAspx() returns an TestAspx.aspx view.
And for the Routing
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"TestAspx",
"testganesh",
new { controller = "Home", action = "TestAspx" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
Please make appropriate changes to the routing names that you need.
Hope this will help.
Let me know if you still face any issue.
Mark as right if the issue got fixed.
:)

Trying to access Index of MVC controller, Exception

So.. i have a MVC webpage. I have defined a Controller
public class NinjaController : Controller
{
// GET: Ninja
public ActionResult Index()
{
return View();
}
}
The my routes are set up like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute("Default", "{controller}/{action}/{id}", new
{
controller = "Login",
action = "Login",
id = UrlParameter.Optional
});
}
}
And i have a Folder in the Views folder that is named Ninja and an Index.cshtml file in there that looks like this:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
Very simple... This is a business application with lots of different settings and configurations... If i do the exact same thing in a new solution it works just fine...
However when i try to access (http://localhost:1235/Ninja) view i get the following error:
{"A public action method 'Login' was not found on controller 'Stimline.Xplorer.Web.Controllers.NinjaController'."}
To me it seems like there should be something confusing the routing function.. but i have no idea where this logic could be placed... anyone have any suggestions?
Interesting fact: If i change the name of the method from Index() to OhYea() and create a corresponding view everything works as expected....
Your routing configuration is saying that pretty much all routes should go to Login which is why your Ninja route doesn't work.
The recommended way of enforcing authentication against a particular route is to use the AuthorizeAttribute. To summarise, keep your default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Ninja", action = "Index", id = UrlParameter.Optional }
);
But restrict your NinjaController to authorized users only
[Authorize]
public class NinjaController : Controller
{
...
}

Categories