Strange behaviour with controller and view inside area MVC 5 - c#

I have one area called user.
The area configuration looks like this
context.MapRouteLowercase(name: "User_Member", url: "User/Member", defaults: new { controller = "User", action = "Member", id = UrlParameter.Optional });
When I browse to this page without passing in a id, it returns the view my url looks like this /user/member
When I type the following into the browser /user/member/1
I've put a break point on
var userId
and it gets hit and I check the id parameter and its 1 which is correct.
[HttpGet]
[Authorize]
public ActionResult Member(Int64 id = 0)
{
var userId = id != 0 ? id : ReturnUserId();
var model = _userProfileBusinessLayer.GetProfile(userId);
return View(model);
}
Yet when I press F5 I get the following page
Server Error in '/' Application.
The view 'member' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/user/member.aspx
~/Views/user/member.ascx
~/Views/Shared/member.aspx
~/Views/Shared/member.ascx
~/Views/user/member.cshtml
~/Views/user/member.vbhtml
~/Views/Shared/member.cshtml
~/Views/Shared/member.vbhtml
I'm unsure why I'm seeing that because all I have done is added /1 to the url?
I should be seeing the profile of the user which matches then id of 1, yet I remove /1 and it returns the view ?!?!?!?! slightly baffled

In your project, the area user should have a class that inherits from AreaRegistration e.g.
public class UserAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "user";
}
}
}
In that class you can define routes sepcific for that area:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"UserManagement",
"user/Admin",
new { controller = "UserAdmin", action = "Index" });
}
The file Global.asax.cs should have an Application_Start() method which calls:
AreaRegistration.RegisterAllAreas();
That will pick up the area routes you have configured. This is usually how area routes are configured. Do you have a similar setup for your project?

Related

Areas Routing in MVC 4 with angularjs

Let me define my setup here. I have some areas like 1. AreaA 2. AreaB 3. AreaC and 4. AreaGeneral. in AreaGeneral I have one controller as home and GetData(paras) and it returns some data either in partial or full page form to angularjs. If I am using these two controller inside the AreaGeneral then its ok. but I want to provide the same controllers inside other Areas like in A, B, and AreaC, but there area and route are different. and more importantly when a user navigates to particular area say AreaB to access GetData(paras) controller then the url should be like .../AreaB/GetData instead of .../AreaGeneral/GetData and the route should work in other areas as well. Can someone guide me how to do this, Thanks.
Givent that you've already had AreaGeneral routes defined as below:
public class AreaGeneralAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "AreaGeneral";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"AreaGeneral_default",
"AreaGeneral/{controller}/{action}/{id}",
new { controller = "Home", action = "GetData", id = UrlParameter.Optional }
);
}
}
You can register that route in AreaB:
public class AreaBAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "AreaB"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"AreaB_Getdata",
"AreaB/Home/Getdata",
new { controller = "Home", action = "GetData" },
new string[] { "areastest.Areas.AreaGeneral.Controllers" }).DataTokens["area"] = "AreaGeneral";
context.MapRoute(
"AreaB_default",
"AreaB/{controller}/{actio‌​n}/{id}",
new { action = "Index", id = UrlParameter.Optional });
}
}
so that user can navigate to .../AreaB/Home/GetData and view the page actually handled within AreaGeneral.
I used angular services in different MVC areas for that I used following way
if your project structure should be like following
>ProjectName
>Areas
>AreaGeneral >controllername >GetData(function)
>AreaA
>AreaB
>AreaC
if your services like
app.service("yourService", ["$http",function ($http) {
this.GetData= function () {
var c = $http({
method: "post",
url:"../AreaGeneral/controllername/GetData",
data: "{}",
dataType: "json"
});
return c
} }])
if you are using inside AreaGeneral then
url "../AreaGeneral/controllername/GetData" ok for that
but when use different area like AreaA
"../AreaGeneral/controllername/GetData" its search inside the AreaA so that you donot get result
Solution work for me like called function adding extra ../ as per root directory structure
this way
"../../../AreaGeneral/controllername/GetData"
then every time call getdata function it checks from root directory so this way you can use Getdata function in any area
Hope this help you.

MVC5 Area not behaving properly

This post is directly related to: MVC5 Area not working
That post fixed the index.cshtml issue, however it did not resolve each view for that controller. For example:
http://localhost:45970/Setup/Start gives the error that the resource cannot be found (basically a 404).
However http://localhost:45970/Setup/Setup/Start brings up the correct page.
So what needs to be reconfigured so that ALL views for that controller in the Setup Area will open properly?
Edit 1
Code from SetupAreaRegistration.cs
using System.Web.Mvc;
namespace BlocqueStore_Web.Areas.Setup
{
public class SetupAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Setup";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Setup_default",
url: "Setup/{controller}/{action}/{id}",
defaults: new { action = "Index", controller = "Setup", id = UrlParameter.Optional },
namespaces: new[] { "BlocqueStore_Web.Areas.Setup.Controllers" }
);
}
}
}
Since you have an Area named Setup with the above route configuration, opening http://localhost:45970/Setup/Start will execute StartController under Setup Area. You got 404 error because you don't have StartController under Setup Area, but you can open http://localhost:45970/Setup/Setup/Start successfully because you have SetupController and Start action method under Setup Area.
Based on your comment, you want the following url patterns
http://{host}/Setup/‌​{view}
http://{host}/Admin/‌​{view}
You can accomplish that without using any Area. You only need AdminController and SetupController using the default route.

Add parameter to all Incoming/Outgoing URL's

I'm having trouble adding a URL parameter to every URL generated, or redirected to in an ASP MVC 4 application.
I want to generate an ID, and use this ID at any point throughout the application. Storing the id in session is not an option as a single session may have multiple browser windows/tabs open concurrently (each with a different id)
RouteConfig
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{customId}",
defaults: new { controller = "Home", action = "Index", customid = UrlParameter.Optional }
);
HomeController.cs
public class HomeController : Controller
{
public ActionResult Index()
{
var customId = Guid.NewGuid();
ControllerContext.RequestContext.RouteData.Values.Add("customId", customId);
//How do I get this redirect to add customid to the url?
//E.g. /Home/Start/{customId}
return RedirectToAction("Start");
//I could do this: But I want it this to happen for every URL,
//and I don't want to replicate this code everywhere
//return RedirectToAction("Start", new { customId = customId });
}
public ActionResult Start()
{
object customId;
//Redirect Loop
if (!Request.RequestContext.RouteData.Values.TryGetValue("customId", out customId))
{
//To generate the ID
return RedirectToAction("Index");
}
ViewData["customId"] = Guid.Parse(customId.ToString());
return View();
}
public ActionResult Next()
{
object customId;
//Redirect Loop
if (!Request.RequestContext.RouteData.Values.TryGetValue("customId", out customId))
{
//To generate the ID
return RedirectToAction("Index");
}
ViewData["customId"] = Guid.Parse(customId.ToString());
return View();
}
}
Not only do I want the ID to be automatically inserted into any Redirect results, but when a View is rendered #Url.Action() and #Html.ActionLink() should also add the ID to the generated URL's.
Start.cshtml
#*Both of these should generate an href="~/Home/Next/{customId}"*#
#Html.ActionLink("Go to Next", "Next", "Home")
Go to Next
How do I automatically add an ID to ALL outgoing routes in ASP MVC?
Create an action filter that will add the ID to the route data in the OnActionExecuting method? You can access the controller through the filter context (and the viewbag). As long as your viewbag contains the customId, you should be able to add it to the route data. At least this way you only need to remember to add the attribute on the controller.
OR
Create a base class that inherits from System.Web.Mvc.Controller and implement your own RedirectToAction. Then have all your controllers inherit form MyControllerBase. Something like this.
public class MyControllerBase : Controller
{
public RedirectToRouteResult RedirectToAction<TController>(Expression<Func<TController, object>> actionExpression)
{
var custId = ControllerContext.Controller.ViewBag["customId"];
string controllerName = typeof(TController).GetControllerName();
string actionName = actionExpression.GetActionName();
return RedirectToAction(actionName, controllerName, new {cId = custId});
}
}
PART 2:
Another way I've modified a URL (I knew I had the code somewhere!) on every view, I needed the URL to link from a mobile site to a full browser site and read the mappings from the database. So in my footer, I have the following:
<a id="fullSiteLink" href="<%= ViewData[AppConstants.MainSiteUrl] %>">Visit our Full Browser site</a><br />
I then added a filter to the base controller class and onactionexecuting (before the action),
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var mainSiteUrl = _mobileToMainRedirect.GetMainSiteUrl(filterContext.HttpContext.Request.Url);
filterContext.Controller.ViewData.Add(AppConstants.MainSiteUrl, string.IsNullOrEmpty(mainSiteUrl) ? UrlHelperExtensions.FullBrowserSite(filterContext.HttpContext.Request.Url) : mainSiteUrl);
}
Complete shot in the dark....
You can set up the route so that if a value is not provided, you create the Id. This way, if the value is there, it will use the provided one. Otherwise, it will create one.
Since this is leveraging the routes, you will be able to generate the Id even when using:
#Html.ActionLink("Go to Next", "Next", "Home")
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{customid}",
defaults: new { controller = "Home", action = "Index", customid = Guid.NewGuid() }
);
NOTE: You would replace Guid.NewGuid() with your own Id generator.

MVC 2.0 View that starts with a number

I'm using c#, visual studio 2010. I'm new to MVC
I was supplied with a simple HTML page that I converted to an aspx view. I then added the controller.
The view directory is Views/150/Index.aspx. The issue is that when I go to add the controller, the class name is not allowed to be a number.
namespace MyPages.Controllers
{
public class _50Controller : Controller
{
public ViewResult Index()
{
return View("Index");
}
}
}
When I entered the have the controller a number, it automatically changed it from 150 to _50. So I changed it to 150Controller.cs and changed the class name to 150Controller : Controller.
Unfortunately, you can't have a number as a class name, and _50Controller as the class name tries to direct to Views/_50/Index.aspx.
I would simply change the name, however I was specifically asked to have it as a number. I know I can set up a redirect in ISS... but is there another way to do this?
Thanks!
In C# members cannot start with a number. You could use routing in order to achieve that:
For example you could have the following controller:
public class ErrorController : Controller
{
public ActionResult Index()
{
return View("500");
}
}
which could be routed like this:
routes.MapRoute(
name: "Error",
url: "500",
defaults: new { controller = "Error", action = "Index" }
);
Now when you navigate to http://example.com/500 it will be the Index action of ErrorController that will get executed and which will render the 500.aspx view.

C# MVC 4, Area Routes, using main views?

I have a basic project with areas in it, I have registered my routes in this area and have used a Lowercase URL extension. Here is the code:
using System.Web.Mvc;
using Web.Modules;
namespace Web.Areas.Services
{
public class ServicesAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Services";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRouteLowercase(
"Services", // Route name
"services/{controller}/{action}/{id}", // URL with parameters
new { controller = "Services", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Web.Areas.Services" }
);
}
}
}
But now when I go to http://localhost/services/home it shows me my HomeController's Index View, what can I do to fix this? I have already added the namespaces and added the area to the routedata.
Thanks for any assistance
Seems like you either don't have the folder Areas/Services/Views/Home at all or the Index view in that folder. In this case, ASP.NET MVC will fallback to displaying your Index view from the Views/Home (no area) folder. If you need a different view for your area, you need to create it in the area's Views/[Controller Name] folder (or the Shared folder, of course).

Categories

Resources