Accessing views between different areas - asp.net-mvc

I have two different Areas (User & Report) and they have two views (Login & Index) respectively.
What I am trying to do is on successful login user should be redirected to Report/Index page but its not working.
Its always inside User area only. Can some one point out what needs to be corrected here. Thanks!!! Help will be appreciated...
public class UserController : Controller
{
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(Models.User user)
{
if (ModelState.IsValid)
{
if (user.IsValid(user.UserName, user.Password))
{
return RedirectToAction("Report/Report/Index");
}
else
{
ModelState.AddModelError("", "Login data is incorrect!");
}
}
return View(user);
}
}
public class ReportController : Controller
{
// GET: Report/Report
public ActionResult Index()
{
return View();
}
}
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 = "User", action = "Login", id = UrlParameter.Optional },
namespaces: new[] { "DWP_MVC.Areas.User.Controllers" }
).DataTokens.Add("area", "User");
routes.MapRoute(
name: "Report",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Report", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "DWP_MVC.Areas.Report.Controllers" }
).DataTokens.Add("area", "Report");
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"User_default",
"User/{controller}/{action}/{id}",
new { action = "Login", id = UrlParameter.Optional }
);
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Report_default",
"Report/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}

Your RedirectToAction() call must include the area name if you are using areas in your MVC structure.
In your example the following code would work:
return RedirectToAction("Index", "Report", new { area = "Report" });
As an aside, if you wish to redirect from one area to a controller/view which is not within the Area folder, you can utilize area = ""

Related

Set up routes where action name is overwriten in the controller

I need to link cultureRoute Route to various methods in the Controllers decorated with [Route("{urlSlug}")] attribute.
Here is my RouteConfig file
using System.Web.Mvc;
using System.Web.Mvc.Routing.Constraints;
using System.Web.Routing;
namespace Site.Web
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "cultureRoute",
url: "{culture}/{controller}/{urlSlug}",
defaults: new { controller = "Home", urlSlug = UrlParameter.Optional },
constraints: new
{
culture = new RegexRouteConstraint("^[a-z]{2}(?:-[A-Z]{2})?$")
});
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{urlSlug}",
defaults: new { culture = "en-GB", controller = "Home", action = "Index", urlSlug = UrlParameter.Optional }
);
}
}
}
And most of my Controllers have this structure
[RoutePrefix("Branded")]
public class BrandedController : ControllerBase
{
[KenticoCacheFilter]
public async Task<ActionResult> Index()
{
return View("../../Views/Project/Index", viewModel);
}
[Route("{urlSlug}")]
public async Task<ActionResult> Project(string urlSlug)
{
return View("../../Views/Project/Individual", viewModel);
}
// Or
[Route("{urlSlug}")]
public async Task<ActionResult> Article(string urlSlug)
{
return View("../../Views/Project/Individual", viewModel);
}
}
So, how do I link the Project() or Article() methods to the CultureRoute as it requires to set the method explicitly in the RouteConfig ?

Right way to Redirect a URL segment to MVC Controller

I have an existing Controller
public class HomeController : Controller
{
public ActionResult Index()
{
return Redirect("/Scorecard");
}
[OutputCache(Duration = 18000)]
public ActionResult Scorecard()
{
return View();
}
}
This currently Maps to http://siteurl/Home/Scorecard . I wanted to the segment http://siteurl/scorecard to redirect to this Controller Action . What would the best wayt to do this . I tried checking the RequestUrl in Session_Start in Global.aspx but the redirects dont seem to be happening . The other alternative I thought of was using a Different Controller like "ScorecardController" and then having a RedirectToAction("Scorecard","Home") in the Index view there.
you could add a FilterAccess class on your App_Start folder to do something like this:
public class FilterAcess : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
//Redirect
if (HttpContext.Current.Request.Url=="http://siteurl/scorecard"){
context.HttpContext.Response.Redirect("~/Home/Scorecard");
}
}
}
RedirectToAction is better way to do it, because, in case you change routing table later, redirect URL will be in adapted.
public class HomeController: Controller
{
public ActionResult Index()
{
return RedirectToAction("Scorecard");
}
[OutputCache(Duration = 18000)]
public ActionResult Scorecard()
{
return View();
}
}
You should also update RouteTable with additional route, before "Default" route:
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "NoHomeSegmentInUrl",
url: "{action}/{id}",
defaults: new { controller = "Home", id = UrlParameter.Optional });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
And, for lower case routes you need line routes.LowercaseUrls = true;

MVC Route static value

I'm not sure if this is possible using mvc routing, I haven't been able to find a similar example.
I have about 5~ controller actions that are the same method, so I'd like to refactor them into a single action. I'd like to pass an enum value to the controller to tell it what path it should pass to lower layers.
Example:
public ActionResult ViewPage(int id, PageEnum page) {
var model = MyService.GetModelForTemplate(id, page);
return ("ViewPage", model);
}
Then the user could access this either through /PagesTypeOne/ViewPage/, or /PagesTypeTwo/ViewPage/. Both routes leading to the same endpoint.
Route table attempt:
routes.MapRoute(
name: "typeOne",
url: "PagesTypeOne/{action}/{id}",
defaults: new { controller = "Pages", action = "ViewPage", id = UrlParameter.Optional, page = PageEnum.TypeOne, }
);
routes.MapRoute(
name: "typeTwo",
url: "PagesTypeTwo/{action}/{id}",
defaults: new { controller = "Pages", action = "ViewPage", id = UrlParameter.Optional, page = PageEnum.TypeTwo, }
);
This obviously isn't working.
Is there a way I can do something like this? It would make my code much more concise.
screen != page, so if the property on the anonymous type matches the parameter it will work:
public ActionResult ViewPage(int id, PageEnum screen) {
var model = MyService.GetModelForTemplate(screen);
return ("ViewPage", model);
}
Updated: Created a empty application and it work flawlessly:
namespace MvcApplication6
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Test1",
"PagesTypeOne/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional,
page = PageEnum.PageOne } // Parameter defaults
);
routes.MapRoute(
"Test2",
"PagesTypeTwo/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional,
page = PageEnum.PageOne } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
public enum PageEnum
{
Undefined,
PageOne,
PageTwo
}
Controller:
namespace MvcApplication6.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult ViewPage(int id, PageEnum page)
{
var debug = 1; // break point
return new EmptyResult();
}
}
}
you can make it completely dynamic with one route definition:
// the route must be defined as the first route
routes.MapRoute(
name: "typeTwo",
url: "{page}/ViewPage/{id}",
defaults: new { controller = "Pages", action = "ViewPage", id = UrlParameter.Optional },
new { page= getPageTypes() }
);
the getPageTypes method:
private static string getPageTypes()
{
var pageTypes = Enum.GetNames(typeof(PageEnum));
return string.Join("|", pageTypes );
}
but PagesTypeOne/ViewPage/4 part must match the enum's name.

Resource not found in Area

I created an Area in MVC then I created a simple controller and I can't view the Area or any page within that part of my site does anyone know why and how to fix this problem. I created a project a while back with an Area and had no problems, I don't know what has changed or if I had to change something to make it work can somebody please help me out.
Somewhere it's not getting registered.
namespace RedPlanet.Areas.admin.Controllers
{
public class CategoryController : Controller
{
}
}
Area:
public class adminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"admin_default",
"admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
Global ASAX:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<DataContext>());
}
}
You need to specify the namespace when registering the route for your admin area and Main Route in you Application.
Main Route :
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "RedPlanet.Controllers" }// specify the namespace
);
In your \Areas\admin\adminAreaRegistration.cs file, you need to modify the RegisterArea() method as follows:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"admin_default",
"admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new[] { "RedPlanet.Areas.admin.Controllers" }// specify the namespace
);
}
Update :
if you are using Guid you should change parameter type of your action method to Guid :
public ActionResult Details(Guid guid)
{
//code
return View(model);
}
then create new route for that ;
routes.MapRoute("FooRouteName",
"Controller/Action/{guidParam}",
new { controller = "Category", action = "Index" },
new { guidParam = #"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$" }
);

Why is homepage of area not being hit?

The director below keeps redirecting to my homepage (Home/Index). I'm not sure why, but I have other areas created called Coaches and Directors, and they work fine. Fiddler only shows a 302 from that dashboard action to the homepage. If I go to /athletes/dashboard/index it works fine.
public virtual ActionResult Dashboard()
{
return RedirectToAction(MVC.Athletes.Dashboard.Index());
}
Global.asax
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index", area="" },
new[] { "Tournaments.Controllers", "Tournaments.Controllers.Api" }
);
Area
namespace Tournaments.Areas.Athletes
{
public class AthletesAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Athletes";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Athletes",
"athletes",
new { action = "Index", controller = "Dashboard", bodyclass = "members" },
new[] { "Tournaments.Areas.Athletes.Controllers" }
);
context.MapRoute(
"Athletes_Dashboard",
"athletes/dashboard/{action}",
new { action = "Index", controller = "Dashboard" },
new[] { "Tournaments.Areas.Athletes.Controllers" }
);
context.MapRoute(
"Athletess_Default",
"athletes/{controller}/{action}",
new { action = "Index", controller = "Dashboard" },
new[] { "Tournaments.Areas.Athletes.Controllers" }
);
}
}
}
Found the issue, I was calling a URL from the coaches area from an ajax request, and it was causing a redirect from the page because the user wasnt in the coach role, and because I had a URL redirect from the Rewrite Module, blah.

Resources