I should create a website with multiple sections. The functionalities and views for these sections are exactly the same but I want different URL such as
For this reason, I created a BaseReferenceController
with all ActionResult
I need. For example:
public class BaseReferenceController : Controller
{
public virtual ActionResult Index(int? sectionId)
{
Articles articles = GetArticles(sectionId);
// more code base on sectionId
return View(articles);
}
// more ActionResult
}
Now I create a new controller to have a new URL Works
like
public class WorksController : BaseReferenceController
{
public override ActionResult Index(int? sectionId)
{
return base.Index(2);
}
}
An error occurs
The view 'Index' or its master was not found or no view engine
supports the searched locations. The following locations were
searched:
~/Views/Works/Index.aspx
~/Views/Works/Index.ascx
~/Views/Works/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Works/Index.cshtml
~/Views/Works/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
My intention was that BaseReferenceController
creates the page and WorksController
returns the ActionResult
comes from BaseReferenceController
.
I tried to use RedirectToActionPermanent
but I can't have the result I want.
Update Forget breadcrumbs.
Update/2
Based on @ironstone13 answer (thanks!) I tried to create a new route:
routes.MapRoute(
"Works",
"Works/{action}/{id}/{slug}",
new { controller = "BaseReferenceController", action = "Index",
sectionId = 2, slug = UrlParameter.Optional },
new { id = @"\d+" });
Where action
is the action
in my Controller
, id
is the identifier of a record to show or edit (if it is necessary), slug
is slug :) but I need a room to pass the sectionId
(because without this I don't know how to filter result).
I received a message in Insight debug
The controller for path '/Works' was not found or does not implement IController.
and in Visual Studio I receive this
System.InvalidOperationException occurred HResult=0x80131509
Message=The constraint entry 'slug' on the route with route template 'Works/{action}/{sectionId}/{slug}' must have a string value or be of a type which implements 'System.Web.Routing.IRouteConstraint'.
Source=System.Web.Mvc
Where am I wrong? After that I can call
? Thanks
One option would be to use custom Action Filter and place your breadcrumb logic there, similar to what was done here:How would you implement a breadcrumb helper in asp.net mvc?
Arguably, breadcrumbs is not the core functionality of your controller methods, so it makes sense to use AOP in the form of custom action filers applied by using attributes, and such infrastructural things should not be the main factor that defines your class hierarchy.
Your current code does not work because index view is searched by convention using invoking controller name, and, obviously, you don't have a view for base controller, and you most probably won't - I assume you need a separate view for each of your entities (Works and OldJobs) - so how will you point to the proper view?.
It is best to avoid passing path to the view altogether and just don't call the View() from the base class.
If the views and controllers for Works and OldJobs are completely the same - it makes sense to have only one view and one controller, and use routing to map different urls to one controller action like below
public class MvcApplication : HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"Works",
"Index",
new { controller = "BaseReferenceController", action = "Index" });
routes.MapRoute(
"OldJobs",
"Index",
new { controller = "BaseReferenceController", action = "Index" });
Update : if you need to pass multiple parameters in the URI consider defining a separate type for your parameters and using parameter binding from uri, see parameter binding from uri. A similar approach is described here Routing with Multiple Parameters using ASP.NET MVC
Your uri could look something like this: //localohost:111/Works/View/?id=23&slug=Document-for-client§ionId=2
.
For multiple parameters using FromUri parameter binding for GET methods, and placing all of the parameters in the QueryString portion of the URI is much cleaner if you don't have some kind of logical hierarchy in your parameters.
If you don't put the parameters in the query string then your URI becomes ambiguous. What does //localohost:111/Works/View/1/2
mean? Is Id=1 and SectionId=2 or vice versa?
MVC convention is that all views use ~/Views/ControllerName/Action
for the view pages by default. If you want it to use a specific view page, you need to specify it in the base controller.
public class BaseReferenceController : Controller
{
public virtual ActionResult Index(int? sectionId)
{
ViewBag.Bread = BreadcrumbHelpers.GetBreadcrumb((int)sectionId);
// more code base on sectionId
return View("~/Views/FolderWhereYourViewIs/View.cshtml");
}
// more ActionResult
}
User contributions licensed under CC BY-SA 3.0