ASP.Net MVC #Url.Action() routing to the wrong controller - c#

I'm newbie to MVC. I could integrate MVC 5.2 to my existing web forms Visual Studio 2012 Update 4 project. I created my first controller and all worked as expected. Even I was able to leverage the windows forms authentication from my existing project when accessing the MVC view. But when created my second controller it began messing up.
It is my route mapping:
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.EnableFriendlyUrls();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
I have two controllers both located in ~/Controllers. My first controller is:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
//return View();
return Redirect("~/Default.aspx");
}
public ActionResult CloseSession()
{
return Redirect("http://www.yahoo.com");
}
}
The second controller:
public class CajaWebController : Controller
{
//
// GET: /CajaWeb/
public ActionResult Index()
{
return View();
}
public ActionResult CloseSession()
{
return Redirect("http://www.cnn.com");
}
}
I don't know is it relevant to the problem but I'll include how the MVC view is reached. My VS2012 start url is
http://localhost/Fortia/CajaWeb.
Fortia is my app name. Because I declared Web Forms authentication and
<location path="CajaWeb">
<system.web>
<authorization>
<allow roles="Fortia" />
<deny users="*" />
</authorization>
</system.web>
</location>
when starting to debug the old WebForms app authentication mechanism is called, the old WebForms login page invoked and after a successful login finally my CajaWebController, Index() action is called. Before creating CajaWebController it was the HomeController who was called, but I assume MVC now deduces the correct controller is CajaWeb because of the targeted url being
http://localhost/Fortia/CajaWeb.
The invoked view contains the following code:
<a href='#Url.Action("CloseSession", "CajaWeb")'>Close session</a>
The problem is when clicking the generated link the MVC calls HomeController.Index() action despite I explicitly set CajaWebController.CloseSession() in the #Url.Action...
I looked at the generated link and it looks wrong:
<a href='/Fortia/__FriendlyUrls_SwitchView?action=CloseSession&controller=CajaWeb'>
it encoded the parameter separator & into & But anyway I tried handcoding the href as
http://localhost/Fortia/__FriendlyUrls_SwitchView?action=CloseSession&controller=CajaWeb
but the result was the same.
What is wrong?

It would seem the ASP.NET Friendly Urls package you're using is interfering with the urls MVC is generating. The library seems to be meant for WebForms anyway
If it works without, then leave it like that as MVC's urls are already quite SEO-friendly when controller and action names are meaningful to their content.

I think the problem is that the route
http://localhost/Fortia/CajaWeb
doesn't match any routes so it ends up going to the default route specified in RouteConfig. You need to configure a route or create an area in your app called "Fortia".

Related

ASP.NET MVC default routh is wrong

I got simple web application with 1 default routing:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Game", action = "Index", id = UrlParameter.Optional }
);
My controller contains the following actions:
public class GameController : Controller
{
public ActionResult Index()
{
// some actions
return View();
}
[HttpPost]
public ActionResult CreateGame(Game game, User user)
{
// some actions
return View("Game");
}
[HttpPost]
public ActionResult JoinGame(User user)
{
// some actions
return View("Game");
}
}
Also under Views/Game folder I got "Index" and "Game" views.
But when I start application from time to time (NOT ALWAYS!) it requests
http://localhost:55815/Game/Game
instead of
http://localhost:55815 or http://localhost:55815/Game/Index
Your application default route is working fine.
The debugger starts url http://localhost:55815/Game/Game because the file Game.cshtml is currently opened in your Visual Studio.
The solution is on your VisualStudio project configuration.
Choose specific page with empty value instead of current/active Page.
Actually,
/Game/Game
and
/Game/Index
are both the same. When you check you default routing file you can see that your main controller is written with predefined controller and action. So the program automatically resolve this url according to that. Mostly try your web application not in visual studio debug but put it under IIS than if you need debugging, debug IIS instance.
Good luck

Automatic URL Parameter Encoding Failing

Background
In HomeController.cs I have:
[HttpGet]
public GetPerson(string name)
{
return View(new PersonModel { ... });
}
In Global.asax.cs I have:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Word", "person/{name}",
new { controller = "Home", action = "GetPerson" });
routes.MapRoute(
"Default", "{controller}/{action}",
new { controller = "Home", action = "Index" });
}
In SomePage.cshtml I have, effectively, this:
#{ var name = "Winston S. Churchill"; }
#name
Problem
If I click the link for Winston S. Churchill, I am routed to the URL http://localhost/person/Winston%20S.%20Churchill, which yields the standard 404 page:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
This only happens if the name variable contains a . (period). All my code works perfectly fine when the name is, for example, Winston Churchill.
How can I make ASP.NET MVC 3 percent-encode the . (period) in the URL?
Or, how can I make the routing work without . (period) being percent-encoded?
Unacceptable Workaround (if presented without justification)
If I change the route to the following, everything works.
routes.MapRoute(
"Word", "person",
new { controller = "Home", action = "GetPerson" });
However, the URL becomes http://localhost/person?name=Winston%20S.%20Churchill, which isn't what I want. I want the name in the path part of the URL, not the query.
Routes which contain a period and unknown extension are interpreted by IIS as static files and not sent through the .NET pipeline. For example, the URL you cite is interpreted as a static file with a %20Churchill extension.
You can force ASP.NET to handle all requests by adding this to web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
You'll also need this, to handle name values that end with a period (as opposed to just containing one):
<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
</system.web>
All /person/{name} URLs will then be picked up by your ASP.NET code.
If you would rather not use this setting, the easiest workaround would be to use a custom encoding:
name.Replace(".","--")

Server Error in '/' Application in ASP.NET MVC 3 with Razor engine

I just created a new ASP.NET MVC 3 project with the Razor engine. I added a controller to the controller folder, and then at homController.cs I added a view.
The View (index.cshtml) has only this code:
#{
ViewBag.Title = "Home";
}
<h2>Home</h2>
And when I start debugging it shows me this error:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.225
What's the problem?
Could you check the App_Start/RouteConfig.cs, you must have this code for a controller called homController.cs :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "hom", action = "Index", id = UrlParameter.Optional }
);
}
I suppose, your first controller name isn't 'Home', so you have to change the default controller name !
Check your routing entries in Application_Start in global.asax since you're using MVC 3. like "Joffrey Kern" suggested, you need to have the routes configured.
also make sure your controller is named "HomeController" and you have a public method called "Index" that returns an ActionResult object.
In ASP .NET MVC 3 your routes are defined in the global.asax
You can find that in the website root.
By default it looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
This means when you call the website root with no parameters, it uses the default values - in this case home/index.
So you need to make sure you:
have a controller called home
an Action called index that returns an ActionResult
Alternatively you can update the default values in the routes, although if you are just starting out I would not recommend this.
It doesn't have to be your routes ... It could be faulty configurations in web config
If you getting this error I highly recommending you to change your public class name. Give a new name as a "HomeController":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyFirstMVC.Controllers
{
public class HomeController : Controller
{
// GET: /First/
public string Index()
{
return "Jay Swaminarayan"; // this string will be display at your run time!!!
}
}
}
THis is ravinder akula
Please find this answer
Right click on your mvc project
Choose "Properties"
Select the "Web" tab
Select "Specific Page"
Assuming you have a controller called HomeController and an action
method called Index, enter "home/index" instead of
home/index.cshtml in to the text box corresponding to the
"Specific Page" radio button.

Asp.net mvc sub-controller

I have to create a site structure like this
/demo/
/demo/admin/create
/demo/admin/edit/id
I can create a DemoController which will contains admin. But how to show create/edit pages? The create/edit pages can be accessible only after user is logged in. Where to put create/edit pages?
If you are certain that you should implement strictly that URL strusture, then maybe "areas" solution would fit you (though not sure, just had a brief view). But I think, that for a small project you could simply make:
separate "admin" controller (that would lead to /demo, /admin/create, /admin/edit/id);
or you could possibly use custom ASP.NET Routing;
As for the authorization, you should look into ASP.NET Web Application Security and User authentication and authorisation in ASP.NET MVC
All you need to do is create a route for /demo/admin, then assign that route to a new controller called DemoAdminController. To make this only accessible to logged in users, you use the Windows Forms authentication system. A sample is provided with the default application generated by MVC.
i agree an area should do the trick or you can add a custom route that points the the controller if you want to lock down the whole section as an admin only section i think areas would be the way to go on this one
Pretty old question, Google landed me here right now.
There is also another way to reach the goal: the Route and RoutePrefix attribute.
Just a small chunk of code for reference.
[RoutePrefix("demo")]
public class DemoController : Controller
{
[Route("")]
public ActionResult Index() { } // default route: /demo
[Route("admin/create")]
public ActionResult Create() { } // /demo/admin/create
[Route("admin/edit/{id}")]
public ActionResult Edit(int id) { } // /demo/admin/edit/5
}
For this to work, the attribute routing must be enabled. In most case is enough to add:
routes.MapMvcAttributeRoutes();
in RouteConfig.cs.
Example:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Dashboard", action = "Index", id = UrlParameter.Optional }
);
}
I think you are looking to use Areas. See docs here:
http://msdn.microsoft.com/en-us/library/ee671793.aspx

Asp .net mvc 2 forms authentication not working on iis 6. Need helps determining correct routes

I'm trying to setup Forms Authentication in an asp.net mvc 2 application that will be hosted on IIS 6. There's an issue somewhere in my routing, but I can't pinpoint exactly where it is.
Here is the route entries I'm using to route the mvc requests through the aspx processing on IIS 6. These may or may not be the "right" way, but they do work on the server at current.
routes.MapRoute(
"Default",
"{controller}.aspx/{action}/{id}",
new { action = "LogOn", id = "" }
);
routes.MapRoute(
"Root",
"",
new { controller = "Main", action = "LogOn", id = "" }
);
I've put the [Authorize] attribute on my Main controller.
In my web.config I have:
<authentication mode="Forms">
<forms loginUrl="~/Main.aspx/LogOn" timeout="2880"/>
</authentication>
When the application starts, a blank page loads. The page is quite literally blank. I haven't found a way to amend the loginUrl to actually execute the LogOn action & View for my Main controller.
Edited
Just as an fyi, I've setup my routing based on this article so that the mvc routing can work on IIS 6.
http://www.asp.net/mvc/tutorials/using-asp-net-mvc-with-different-versions-of-iis-cs
I'm guessing the problem here is that the windows form authentication settings aren't syncing with the routes setup so the app can run on IIS 6 via the aspx extension.
Anyone have thoughts on how I could fix this?
Edit 2
Tried adding the following route:
routes.MapRoute(
"Login",
"Login",
new { controller = "Main", action = "LogOn" }
);
Amended the web.config to:
<authentication mode="Forms">
<forms loginUrl="~/Login" timeout="2880"/>
</authentication>
The result is the same white screen as I originally got. It seems like the page doesn't get processed at all. Viewing the source from page generated shows absolutely nothing....no markup...no html declaration....just nothing.
EDIT 3
It seems that I can't seem to get the correct routing configured with the default forms authentication via the web.config. To circumvent this, I've created my own Authorize attribute class. At current, I only care that the user has logged into the system. To accomodate this, I moved the LogOn & LogOff actions to an Account controller. I've remapped the root path to point to this controller. In my custom Authorize attribute, I check to see if the user is logged in and redirect them back to the LogOn page if they aren't. Here is the code:
routes.MapRoute(
"Root",
"",
new { controller = "Account", action = "LogOn", id = "" }
);
And here's the code for the RequireLoginAttribute class I derrived.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireLoginAttribute : AuthorizeAttribute, IAuthorizationFilter
{
#region IAuthorizationFilter Members
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated)
{
//This didn't work...it would try routing to urls like
//http://localhost:1524/Main.aspx/Account.aspx/Logon
//new RedirectResult("Account.aspx/Logon");
//This seems sloppy to me somehow, but it works.
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Account", action = "LogOn" }));
}
}
#endregion
}
Now, I can just apply the [RequireLogin] attribute to the Main controller and it ensures the user must be authenticated.
For the curious, and completeness of this scenerio, I am using the following code in the LogOn action (repository isn't ready yet so things are hard coded):
public ActionResult LogOn(LogOnModel login, String returnUrl)
{
if (ModelState.IsValid)
{
FormsAuthentication.SetAuthCookie(login.UserName, false);
return Redirect(returnUrl ?? Url.Action("NextPage", "Main"));
}
else
{
return View(login);
}
}
The returnUrl is a throwback to the Windows Forms authentication. Since I can't seem to get that working here, the parameter will always be null.
Please, critique this if you see specific areas that need improvement. I'm reading what I can and trying to do things right, so all input is greatly appreciated. Thanks!
If you need the .aspx for the Default Root then why don't you need it for the login route ?
You could do a couple of things then
Actually create a ASP.NET page called Login.aspx and put it in the root of the folder (Authentication will work for your mvc pages as well)
Change your login route to say
routes.MapRoute("Login","Login.aspx",new { controller = "Main", action = "LogOn" });
You should also take a look at to see what route your actually hitting at any time.
http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Remember that the order you write your routes in Global matters. It stops checking when it finds one that works so your catch all should be last.
The details I posted in EDIT 3 summarize the solution to this issue. I appreciate all of your input into this question, but I've resolved it. I would have liked to have gotten the "out of the box" forms authentication working, but this solution serves well enough. If we move to IIS 7, I think all of this will become moot anyhow.
Thanks again for your help guys.

Categories

Resources