ASP MVC 5 Route Mapping - c#

Insides my views folder I have a 'User' folder, this does not contain a corresponding view, but contains sub folders which will contain a view.
Example:
User
Create
create.cshtml
Edit
edit.cshtml
I then have one controller, currently only with one action for create:
public ActionResult Create() {
return View("Create/Create");
}
So to hit that action I go to user/create, and that returns the view fine.
The problem comes from when I am trying to link to that view in an <a> tag using Url.RouteUrl. It errors and says:
A route named 'user/create' could not be found in the route collection
But to me, it matches the default route in the route config: controller/action.
Here is my RouteConfig:
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Turn on attribute routing in the controllers
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
controller = "Home", action = "Index", id = UrlParameter.Optional
}
);
}
So why do I need to define a custom route for it?

You don't need to define a custom route for it, but you need to follow the convention for your folders. Put the create.cshtml and edit.cshtml views directly inside the User folder, and delete the Create and Edit subfolders, you don't need them.
Now, in the controller, you can simply use:
public ActionResult Create() {
return View();
}
It knows what to look for and where to find it, so it will pick your User/create.cshtml view successfully. However, we usually pass a model to our views. In such a view like the Create, the model is used to build all the controls (textboxes, labels, etc):
public ActionResult Create() {
var model = new UserViewMode();
return View(model);
}

Related

403.13 when using action link to go to {controller}/Index

I am getting the following error when debugging my header links.
I have tried recreating my Index.cshtml (Empty and with Razor/HTML) and my ServicesController.
If I browse to Services/Index explicitly then the page loads up correctly.
IE: localhost:58069/Services/ does not work but localhost:58069/Services/Index does
My other controllers are working correctly using the same structure and ActionLink helper.
Not working code:
public class ServicesController : Controller
{
// GET: Services
public ActionResult Index()
{
return View();
}
}
Action Link HTML Helper for Services/Index
<li>#Html.ActionLink("Services", "Index", "Services")</li>
Working Code
public class HomeController : Controller
{
// GET: Home/Index
public ActionResult Index()
{
return View();
}
}
Working Helper
<li>#Html.ActionLink("Welcome", "Index", "Home")</li>
Route Config
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Tried the following SO solutions:
ASP MVC in IIS 7 results in: HTTP Error 403.14 - Forbidden
This behavior is caused by the Services folder (below Scripts folder) you have in your project. When hosting in IIS, you should not have a file or folder with the same name as your ASP.NET route.
Ways to solve this:
routes.RouteExistingFiles = true; will let ASP.NET handle all the routing
Rename your Services folder or controller
Move Services to a separate library and remove the folder from the web project
I'd recommend the latter option as settings RouteExistingFiles to true would need additional research to double-check you're not opening any security holes and it cleans up your web project (a little bit of separation never hurts).

How do I get ASP.NET to route a controller properly?

I have this in my controller:
public ActionResult Details(int? id)
{
if(id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Sales saleRecord = new Sales();
var result = saleRecord.GetSalesOrderHeader((int)id);
return View(result);
}
However if I browse to /ControllerName/Details/5 I get this error:
"Server Error in '/' Application. - The view 'details' or its master was not found or no view engine supports the searched locations."
The strange thing is that if I use ASP.NET Scaffolding to generate a view, the Details part of that works fine. It's basically the same code I have above as well.
Here's my RouteConfig.cs, if that's relevant:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
So why is that the scaffolding controller works fine, without having anything specific added to RouteConfig, yet my controller Details method is not working?
There should be more detail in error that what locations have been searched. Did you put break point in controller and checked if its being hit?
try
return View((object)result);
instead of
return View(result)
cause its calling overload View(string viewName)
If this doesn't work, try to specify viewName explicitly like this:
return View("ViewName", name);
Additionally, check your folder structure. MVC looks for views (like Index) under the views folder but they also have to be under a folder named after their controller (except partial views).

How to call a controller outside of an area?

In my application I have an area "Member".
Outside this member area I have a folder named "Generic" which is having a controller "DataBindController".
This controller will be used in all areas. So to keep it common, i am keeping it in a separate folder outside of areas.
My route config is as follows:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var ObjRoute = routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults:new {controller = "Login", action = "MemberLogin", id = UrlParameter.Optional},
namespaces: new string[] { "MyApp.Generic.*" }).
DataTokens = new RouteValueDictionary(new { area = "Member"});
//ObjRoute.DataTokens["UseNamespaceFallback"] = false;
}
}
Here's the project directory structure.
The Test controller inside Generic folder is as follows:
namespace MyApp.Generic
{
public class DataBindController : Controller
{
public ActionResult Test()
{
return Content("Test");
}
}
}
I am getting following error when I call the test controller using "http://localhost/MyApp/Generic/DataBind/Test"
Error in Path :/MyApp/Generic/DataBind/Test The controller for path
'/MyApp/Generic/DataBind/Test' was not found or does not implement
IController.
Please give me some idea on this issue.
your address doesn't match your defined route. Generic is just a folder. MVC doesn't care about the folder your controller is in.
the correct one should be like this :
http://localhost/MyApp/DataBind/Test
so the DataBind will be the controller and Test the Action.
Update:
your route is
{controller}/{action}/{id}
When you have Generic in your address, Asp.net matchs parts this way : Generic is the Controller, DataBind is Action and Test is the Id. of course it can't find such a thing. But when you remove Generic , every part goes to its real place.
To have Generic in the address, you should change your route to this:
Generic/{controller}/{action}/{id}
To read more about routing :
http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/asp-net-mvc-routing-overview-cs

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
{
...
}

Must the first view must always be called index.aspx?

I have created a controller called loginController.cs and i have created a view called login.aspx
How do I call that view from loginController.cs?
The ActionResult is always set to index and for neatness, I want to specify what view the controller uses when called rather than it always calling its default index?
Hope that makes sense.
You can customize pretty much everything in MVC routing - there is no particular restriction on how routes look like (only ordering is important), you can name actions differently from method names (via ActionName attribute), your can name views whatever you want (i.e. by returning particular view by name).
return View("login");
In the interest of actually answering the question.. you can add a route ABOVE your default route in Global.asax:
routes.MapRoute(
"SpecialLoginRoute",
"login/",
new { controller = "Login", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
..although, without properly thinking through what you're trying to achieve (that being.. changing what MVC does by default) you're bound to end up with lots and lots of messy routes.
Your return the view from your controller via your Action methods.
public class LoginController:Controller
{
public ActionResult Index()
{
return View();
//this method will return `~/Views/Login/Index.csthml/aspx` file
}
public ActionResult RecoverPassword()
{
return View();
//this method will return `~/Views/Login/RecoverPassword.csthml/aspx` file
}
}
If you need to return a different view (other than the action method name, you can explicitly mention it
public ActionResult FakeLogin()
{
return View("Login");
//this method will return `~/Views/Login/Login.csthml/aspx` file
}
If you want to return a view which exist in another controller folder, in ~/Views, you can use the full path
public ActionResult FakeLogin2()
{
return View("~/Views/Account/Signin");
//this method will return `~/Views/Account/Signin.csthml/aspx` file
}

Categories