locked
[CORE MVC] How to get parent controller name in a partial view? RRS feed

  • Question

  • User-1657171777 posted

    I have a partial view that I share over multiple controllers.  I would like the partial to obtain the parent controller name, and then use conditionals to change some things within the partial based on which parent controller is calling the partial.

    @if (ParentControllerName == "Home")
    {
        // do this
    }
    else
    {
        // do that
    }

    Monday, March 15, 2021 5:01 PM

Answers

  • User475983607 posted

    JohnLocke

    This code inside a partial view will return the partial's controller, not the controller of the View that's calling the partial. 

    What you've described is how HTTP works regardless of the framework.  There is one request and one response.   I think you are asking for the controller that generated an AJAX/JavaScript application.  Your AJAX function must pass the controller name to the action that returns the partial content.

        public class AjaxController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
        }
    @model MvcDemo.Controllers.ViewModel
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    <div>
        <input id="Button1" type="button" value="button" />
    </div>
    <div id="response">
    
    </div>
    
    @section scripts {
        <script>
            $('#Button1').click(function () {
                $.ajax({
                    method: "GET",
                    url: '/home/GetObjectPartial/1/?orignalController=' + '@ViewContext.RouteData.Values["controller"].ToString()',
                }).done(function (response) {
                    $('#response').html(response);
                });
            });
        </script>
    }
        public class HomeController : Controller
        {
            private readonly ILogger<HomeController> _logger;
    
            public HomeController(ILogger<HomeController> logger)
            {
                _logger = logger;
            }
    
            [HttpGet]
            public PartialViewResult GetObjectPartial(int id, string orignalController)
            {
                _logger.LogInformation($"id={id} orignalController={orignalController}");
                ViewBag.ParentControllerName = orignalController;
                return PartialView("_ObjectPartial", _db.getObject(id));
            }
    @model MvcDemo.Controllers.ViewModel
    
    
    @if (((string)ViewBag.ParentControllerName).ToUpper() == "Home".ToUpper())
    {
        <div>The Home controller says... @Model.Message</div>
    }
    else
    {
        <div>The @ViewBag.ParentControllerName controller says... @Model.Message</div>
    }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 17, 2021 5:49 PM

All replies

  • User-474980206 posted

    Use can use route data to access the controller name, but a better practice would be to pass it to the partial. Actually you should be using view components instead of partials

    Monday, March 15, 2021 10:44 PM
  • User1686398519 posted

    Hi JohnLocke, 

    According to your needs, I wrote a simple example, you can refer to it.

    TestPartial

        public class TestPartialController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
        }

    TestPartial2

        public class TestPartial2Controller : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
        }

    TestPartial2/Index  Or  TestPartial/Index

    <h1>Index</h1>
    <partial name="_SharedPartialView"/>

    _SharedPartialView

    @{
        var ParentControllerName = this.ViewContext.RouteData.Values["controller"].ToString();
    }
    @if (ParentControllerName == "TestPartial")
    {
    <p>This is TestPartial</p>
    }
    else
    {
    <p>This is TestPartial 2</p>
    }

    Here is the result. 

    Best Regards,

    YihuiSun

    Tuesday, March 16, 2021 9:15 AM
  • User-1657171777 posted

    Use can use route data to access the controller name, but a better practice would be to pass it to the partial. Actually you should be using view components instead of partials


    This is a unique case.  I'm using a 3rd party MVCGrid that utilizes partial views for rendering Ajax content.

    @{
        var ParentControllerName = this.ViewContext.RouteData.Values["controller"].ToString();
    }

    This code inside a partial view will return the partial's controller, not the controller of the View that's calling the partial.  Let me expand:

    HOME controller contains my partial view action.  This partial view can be called by any of my controllers.

    public class HomeController : Controller
    {
        public PartialViewResult GetObjectPartial(int id)
        {
            return PartialView("_ObjectPartial", _db.getObject(id));
        }
    }

    A different controller has a view that calls the above partial. I need to get the parent view's controller name as a value inside the partial view.  So if my parent view is coming from a controller named "Products", the partial view should obtain the parent view's controller name to be used in its logic.  Pre-Core MVC used to have this to get the parent view's controller name from within a partial view.

    var parentController = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()

    In my Pre-Core MVC projects, I could put this code into a shared partial view and get the controller name of the View that called the partial.  This code is no longer valid in Core MVC.  I would just like an equivalent to this for Core MVC if one exists.  Otherwise I'm just going to have to add this partial view action to each controller, but I wanted to avoid the redundancy (keep it DRY).

    Wednesday, March 17, 2021 3:40 PM
  • User475983607 posted

    JohnLocke

    This code inside a partial view will return the partial's controller, not the controller of the View that's calling the partial. 

    What you've described is how HTTP works regardless of the framework.  There is one request and one response.   I think you are asking for the controller that generated an AJAX/JavaScript application.  Your AJAX function must pass the controller name to the action that returns the partial content.

        public class AjaxController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
        }
    @model MvcDemo.Controllers.ViewModel
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    <div>
        <input id="Button1" type="button" value="button" />
    </div>
    <div id="response">
    
    </div>
    
    @section scripts {
        <script>
            $('#Button1').click(function () {
                $.ajax({
                    method: "GET",
                    url: '/home/GetObjectPartial/1/?orignalController=' + '@ViewContext.RouteData.Values["controller"].ToString()',
                }).done(function (response) {
                    $('#response').html(response);
                });
            });
        </script>
    }
        public class HomeController : Controller
        {
            private readonly ILogger<HomeController> _logger;
    
            public HomeController(ILogger<HomeController> logger)
            {
                _logger = logger;
            }
    
            [HttpGet]
            public PartialViewResult GetObjectPartial(int id, string orignalController)
            {
                _logger.LogInformation($"id={id} orignalController={orignalController}");
                ViewBag.ParentControllerName = orignalController;
                return PartialView("_ObjectPartial", _db.getObject(id));
            }
    @model MvcDemo.Controllers.ViewModel
    
    
    @if (((string)ViewBag.ParentControllerName).ToUpper() == "Home".ToUpper())
    {
        <div>The Home controller says... @Model.Message</div>
    }
    else
    {
        <div>The @ViewBag.ParentControllerName controller says... @Model.Message</div>
    }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 17, 2021 5:49 PM
  • User-474980206 posted

    In my Pre-Core MVC projects, I could put this code into a shared partial view and get the controller name of the View that called the partial.  This code is no longer valid in Core MVC.  I would just like an equivalent to this for Core MVC if one exists.  Otherwise I'm just going to have to add this partial view action to each controller, but I wanted to avoid the redundancy (keep it DRY).

    this only worked in pre-core if ajax wasn't used (that is a view invoked the partial). You could have used the ViewcContext to access routedata in pre-core sample code.  The route data is just parsed from the url.

    Wednesday, March 17, 2021 6:11 PM
  • User-1657171777 posted

        url: '/home/GetObjectPartial/1/?orignalController=' + '@ViewContext.RouteData.Values["controller"].ToString()',
                

    Thanks I'll implement this in a way that this Grid control will accept.

    Wednesday, March 17, 2021 6:43 PM