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.
Related
I need to pass some value to the View Component from the controller. I tried differently but it does not transmit. If I don't pass anything to the constructor then everything works fine, but when I try to pass it to the constructor it doesn't even call the ViewComponent
Controller:
[HttpGet]
public IActionResult AddToCart(int id)
{
return ViewComponent("Cart", new {id});
}
View Component:
public class CartViewComponent : Microsoft.AspNetCore.Mvc.ViewComponent
{
int gId;
public CartViewComponent(int id)
{
gId = id;
}
public IViewComponentResult Invoke()
{
return View();
}
}
Invoking a view component includes the following explanation:
The parameters will be passed to the InvokeAsync method.
This means you should move your id parameter from the constructor to the Invoke method:
public class CartViewComponent : Microsoft.AspNetCore.Mvc.ViewComponent
{
public IViewComponentResult Invoke(int id)
{
// Use id here.
return View();
}
}
I have the following code that is identical across multiple Action Methods in my controller. Is it possible to reduce this down to a single method and route multiple Actions to it?
[HttpGet]
public ActionResult Tool2(Guid? id)
{
var model = _viewModelFactory.CreateViewModel<Guid?, ToolsViewModel>(id);
return model.ReferenceFound ? View(model) : View("~/Views/Tools/InvalidReference.cshtml", model);
}
[HttpGet]
public ActionResult Tool1(Guid? id)
{
var model = _viewModelFactory.CreateViewModel<Guid?, ToolsViewModel>(id);
return model.ReferenceFound ? View(model) : View("~/Views/Tools/InvalidReference.cshtml", model);
}
Each Action does has a unique View and this needs to be retained.
Make a common method which both actions will call. Leave both actions separate as it will be clearer to understand than to write (and read!) custom routes.
public ActionResult Tool1(Guid? guid)
{
return CommonAction(guid, "Tool1");
}
public ActionResult Tool2(Guid? guid)
{
return CommonAction(guid, "Tool2");
}
private ActionResult CommonAction(Guid? guid, string viewName)
{
var model = _viewModelFactory.CreateViewModel<Guid?, ToolsViewModel>(id);
return model.ReferenceFound ?
View(model) : View("~/Views/Tools/InvalidReference.cshtml", model);
}
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'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.
I ve got 2 seperate controller sheets not just action methods..
MY First Controller:
namespace TestLokal.Controllers
{
public class BOUNCEController : Controller
{
BOUNCEDataDataContext db = new BOUNCEDataDataContext();
//
// GET: /BOUNCE/
[Authorize]
public ActionResult Index()
{
ViewData["Bouncers"] = new SelectList( db.Bouncers.Distinct(), "bouncer_id", "bouncer_name");
return View();
}
}
}
MY Second Controller:
namespace TestLokal.Controllers
{
public class DopplerController : Controller
{
//
// GET: /Doppler/
[Authorize]
public ActionResult Index()
{
elementmodel dop = new elementmodel();
ViewData["Dopplers"] = new SelectList( dop.BouncerList.Distinct(), "bouncer_id", "bouncer_name");
return View();
}
}
}
i wanna transfer data from first to second by using this model:
MY Model:
public class elementmodel
{
public IEnumerable<Bouncers> BouncerList { get; set; }
}
How can i achieve this?
You can use TempData for this.
See http://msdn.microsoft.com/en-us/library/dd394711(v=vs.90).aspx (passing data between action methods)
First of all ... are you sure you need two separate controller that has same data? In my humble opinion each controller should be responsible for handling his own group of models. If you need to have the same data in both of controllers maybe you should create some base class?
public class MyBaseController : Controller
{
//shared fields & methods for example datacontext
}
public class DopplerController : MyBaseController
{
}
public class BounceController : MyBaseController
{
}
but if I'm wrong and one of your controller just need results of work from another controller you can use Coockies, Session.
2 things come immediately to mind.
You can store the list of bouncers in the View as a JSON object
that gets POSTed off to the other controller.
You can use TempData to store it between requests. eg: http://msdn.microsoft.com/en-us/library/dd394711.aspx