I'm trying to set up route hijacking on Umbraco 7 with little success.
I have a view called Home.cshtml, the top few lines of which are:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = "Master.cshtml";
}
I added a controller:
-EDIT-
updated question to include Index() controller action.
namespace CLIAUmbraco7.Controllers
{
public class HomeController : Umbraco.Web.Mvc.RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
string country = "";
return base.Index(model);
}
public ActionResult Index()
{
return View();
}
}
Sticking a breakpoint on the Layout line catches the site before it loads but HomeController is never called. Any idea what I'm doing wrong?
By default the controller needs to be called
[TheDocumentTypeAliasYouWantToHijack]Controller
If your document type is not "Home" then it will not be intercepted.
You are missing an Index() controller action. Your controller should look like this:
public class HomeController : Umbraco.Web.Mvc.RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
//Do some stuff here, then return the base method
return base.Index(model);
}
}
Take a look at the article on Umbraco website.
Related
I am thinking about a scenario rather similar to this question asked some time ago: How to call another controller Action From a controller in Mvc
In the scenario I am thinking of, controller B would however return a partial view that I would like to incorporate into the ViewResult returned by the Home controller, so the code might look like this:
public class Home
{
public ActionResult Index()
{
ActionResult partialViewFromCtrl_B = RedirectToAction(actionName: "SomeAction",
controllerName: "Controller_B");
// The returned view should include the partial view `partialViewFromCtrl_B`
return View();
}
}
public class Controller_B
{
public ActionResult SomeAction()
{
// Do some stuff
return PartialView(viewName: "_SomeAction", model: someModel);
}
}
Is there a way to combine the partial view returned from controller B into the view returned from the Home controller?
If possible, I would like to keep the logic and the views defined for controller B separate from the Home controller rather than merging everything into the Home controller.
Your help is very much appreciated!
Edit:
One possible solution to my scenario might by if the Index.cshtml of the Home controller looks like this
#model SomeModelType
...
#Html.Partial(partialview: "~/Controller_B/_SomeAction", model: Model)
...
and the Index() action of the Home controller would look like this:
public ActionResult Index()
{
// Get the model from Controller_B instead of the partial view
SomeModelType someModelFromCtrl_B = new Controller_B().returnSomeModel();
return View(someModelFromCtrl_B);
}
This however does not seem to be the best approach to take here for me.
So if possible I would like to combine the partial view Controller_B/_SomeAction and the Index view of the Home controller in the action method of the Home controller if that is possible.
Through the code posted I can not understand what you want to return.
based on your little code I think you intend to return Index values in PartialView.
Take a look at the code below:
public class Home
{
public ActionResult Index()
{
if(//cond){
// Do some stuff
return PartialView(viewName: "_SomeAction", model: someModel);
}
else{
ActionResult partialViewFromCtrl_B = RedirectToAction(actionName: "SomeAction",
controllerName: "Controller_B");
// The returned view should include the partial view `partialViewFromCtrl_B`
return View("Index");
}
}
}
I'm trying to pass the name of Home controller to Article controller based on which I'm trying to assign a _layout page.
Following is my code which i have tried.
public class HomeController : Controller
{
public ActionResult Index()
{
TempData["Ctrl"] = "Home";
}
}
public class ArticleController : Controller
{
public ActionResult Index()
{
if (TempData["Ctrl"] != null)
{
return View("Index", "~/Views/Shared/_Layout.cshtml", articles);
}
return View("Index", "~/Views/Shared/_otherLayout.cshtml", articles);
}
}
The problem is I'm assigning TempData value in each and every method in the Home controller (which I don't want to do it) as I'm losing TempData value. I tried assigning the value in the constructor of home controller without luck.
Could anyone please help me or point me in the right direction thanks.
You can assign your data in the Session object
this.HttpContext.Session.Add("Ctrl","Home")
I am writing an application using ASP.NET MVC 5 using c#. I have a need to add a global menu on the upper right hand side of the application. I was advised other SO to use action with ChildActionOnly attribute.
So here is what I have done.
I created a BaseController like this
public class BaseController : Controller
{
[ChildActionOnly]
public ActionResult ClientsMenu()
{
using (SomeContext db = new SomeContext())
{
return PartialView(db.Database.SqlQuery<Client>("SELECT * FROM clients").ToList());
}
}
}
Then I inherited all my controllers from BaseController like so
public class TasksController : BaseController
{
public ActionResult Index(int ClientId)
{
...
return View();
}
public ActionResult Show(int SurveyId)
{
...
return View();
}
}
To render the ClientsMenu in my layout I added the following code
#Html.Action("ClientsMenu", "Menus")
Now when I run my application I get the following error
The controller for path '/Tasks/Index' was not found or does not implement IController.
When I remove #Html.Action("ClientsMenu", "Menus") from the layout everything works fine but the global menu does not show of course.
What can I do to resolve this issue?
Updated
Here is what I have done after the feedback I got from the comments below
public class TasksController : Controller
{
[ChildActionOnly]
public ActionResult ClientsMenu()
{
using (SomeContext db = new SomeContext())
{
return PartialView(db.Database.SqlQuery<Client>("SELECT * FROM clients").ToList());
}
}
public ActionResult Index(int ClientId)
{
...
return View();
}
public ActionResult Show(int SurveyId)
{
...
return View();
}
}
but still the same error
Take ClientMenus Action out of the BaseController and put it into its own controller MenusController. You can then call that controller from your Views.
#Html.Action("ClientsMenu", "Menus")
In your example you don't have a MenusContoller which is what #Html.Action("ClientsMenu", "Menus") is looking for.
The Phil Haacked - Html.RenderAction and Html.Action article linked to by the other post provided a good example for you to follow.
I have a target to create a nested architecture of view/controller. For example:
we have few areas in webpage. All this areas managed by its own controller. In another words I need to create independend pages and then join them in one page.
Please see the image:
So is it possible and where I can read about it? Thanks.
Yes you can achieve this by simply calling
#Html.Action("ActionName", "ControllerName");
Example:
in your case you can do like this
Controller1
public ActionResult View1()
{
return View("View1");
}
Controller2
public ActionResult View2()
{
return View("View2");
}
Controller3
public ActionResult View3()
{
return View("View3");
}
Calling in main page:
#Html.Action("View1", "Controller1");
#Html.Action("View2", "Controller2");
#Html.Action("View2", "Controller2");
call these in different section of main page wherever you want.
You can use #Html.Action() to render child views from different controllers
public class FirstController : Controller
{
public ActionResult Index()
{
return View();
}
}
public class SecondController : Controller
{
[ChildActionOnly]
public ActionResult Method1()
{
return PartialView();
}
}
public class ThirdController : Controller
{
[ChildActionOnly]
public ActionResult Method2(int ID)
{
return PartialView();
}
}
Index View (FirstController)
....
#Html.Action("Method1", "Second")
#Html.Action("Method2", "Third", new { ID = someValue })
You can also use #{ Html.RenderAction(); which is more efficient is you are generating a lot of html.
I am currently building a user login system in MVC 5 for practice. What I wanna do is, making a controller only accessable if you have the session "UserId".
Surely, I could just make an if statement in every action, like this:
public ActionResult Index()
{
if (Session["UserId"] != null)
{
return View();
}
else
{
return RedirectToRoute("Home");
}
}
But is there a way I can make that happen with all the actions in the controller?
Bonus info:
I have 2 controllers
- HomeController
- AccountController
You would implement an authorize filter and apply that filter to your controller.
Something like this:
public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
if (filterContext.HttpContext.Session["UserId"] == null)
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
Then you could apply the [CustomAuthentication] attribute to your controller directly, or you can do it by each action in your controller. Something like this:
[CustomAuthentication]//<-- If you put it here, it applies to the whole controller
public class HomeController : Controller
{
[CustomAuthentication]//<-- Here it only applies to the Index action
public ActionResult Index()
{
return View();
}
}
I believe what you are looking for is a custom ActionFilter. Code in an ActionFilter can be executed before the ActionResult, allowing you to redirect anyone without the UserId session.
Instead of putting code in every ActionResult you would do something like this
[MyCustomActionFilter]
public ActionResult Index()
{
return View();
}
Here is a tutorial on how to create one Custom Action filters in MVC