1

I'm trying to call controller and a view from it dynamically, I'm retrieving controller name and view name from database, then I want to execute that as the view result of Page/Index url.

Basically I'm trying to do something like this:

public class PageController : Controller
{
    public ActionResult Index()
    {
        var controllerName = // logic to get Controller name (already have)
        var ViewName = // logic to get View name (already have)

        Return View(ControllerName, ViewName); // I want to achieve this functionality without redirect

    }

}

I have tried Server.TransferRequest but that causes HttpContext.Items to be cleared which I don't want it to happen, also I don't want to redirect, Is there any other way?

HappySylveon
  • 73
  • 2
  • 10
  • Are you simply trying to get the result of another controller and action, without a redirect? – Tieson T. Sep 19 '16 at 18:50
  • 1
    This might help you to get you answer : http://stackoverflow.com/questions/18248547/get-controller-and-action-name-from-within-controller – Yatendrasinh Joddha Sep 19 '16 at 18:56
  • @TiesonT. Yes exactly – HappySylveon Sep 19 '16 at 19:15
  • Do you have to implement that logic in your PageController? Can't you use Global.asax? – Sparrow Sep 19 '16 at 19:35
  • @FeryalBadili I want the functionality of `RedirectToAction()` but **without redirecting** the user that's all, I don't know what do you mean by using Global.asax – HappySylveon Sep 19 '16 at 19:43
  • See this - http://stackoverflow.com/questions/6802789/asp-net-mvc-redirect-to-action-without-a-physical-redirect – AT-2017 Sep 19 '16 at 19:48
  • @AT-2016 unfortunately I have controller name and view name stored as string which means I cannot do `Return C.V();` unless if I could make the controller object from its name. – HappySylveon Sep 20 '16 at 06:43
  • Could you be more specific I mean try to share the scenario or some more sample code? – AT-2017 Sep 20 '16 at 08:52
  • Your question is not clear – Liam Sep 20 '16 at 11:50
  • @AT-2016 Please look at sample code I provided in question, I'm explaining the logic I want to achieve, I want to call controller and a view from it by using two string values of their names. Basically like `RedirectToAction` but without any redirection. I'm dynamically retrieving controller name and view name from database and I want to 'execute' that as result for Page/Index – HappySylveon Sep 20 '16 at 11:51
  • @Liam How about now? – HappySylveon Sep 20 '16 at 11:55
  • so you want to call an action or render a view? Because they are different things – Liam Sep 20 '16 at 11:56
  • 1
    I need a View Result from having the controller name and view name, that view result should be for Page/Index so it's basically like a redirect but without an actual redirect so the browser doesn't get 302 status code – HappySylveon Sep 20 '16 at 12:00
  • I've added an answer but I wouldn't reccommend it. TBH this sounds like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Liam Sep 20 '16 at 12:09

4 Answers4

2

It is simple...But i think of some other reason you want something like this..

public class PageController
{
    public ActionResult Index()
    {
        //Let 
        var controllerName = "Common"// logic to get Controller name (already have)
        var ViewName = "Index" // logic to get View name (already have)

        return RedirectToAction("Index", "Common", new { id = "1" }); 

    }

}

and in Controller

public class CommonController : Controller
    {
        // Initialize with Default value
        public ActionResult Index(String id = "0")
        {
            //Call from PageController
            if (id == "1")
            {
                //Do some stuff
            }
            //Do other stuff of CommonController 
            return View();
        }
 }
Syed Mhamudul Hasan
  • 1,341
  • 2
  • 17
  • 45
2

So presuming, you want to return a the result of an action based on strings. You could use reflection to do this. So something along the lines of:

public ActionResult Index()
{
    var controllerName = // logic to get Controller name (already have)
    var viewName = // logic to get View name (already have)


    //get the current assembly
    Type t = typeof(PageController);
    Assembly assemFromType = t.Assembly;

    //get the controller type from the assembly
    Type controllerType = assemFromType.GetType("Namespece." + controllerName);

    //get the action method info
    MethodInfo actionMethodInfo = controllerType.GetMethods(viewName);

    //create an instance of the controller
    object controllerInstance = Activator.CreateInstance(controllerType, null);
    //invoke the action on the controller instance
    return (ActionResult)actionMethodInfo.Invoke(controllerInstance, null);
}

This is untested and TBH I wouldn't recommend doing this. It's far from efficent.. there also an assumption here that your action doesn't need parameters which may or may not be true. The other option (and almost definitely the better option) is to use a Redirect as discussed by other people.

With this MVC still might have problems locating the view. You may also need to hard code your view path in the action you want to invoke. Basically what you want is very problematic and have I mentioned I wouldn't recommend doing this

Community
  • 1
  • 1
Liam
  • 27,717
  • 28
  • 128
  • 190
  • Thank you I will try it and report back – HappySylveon Sep 20 '16 at 12:45
  • For some reason I get error: "The view 'Index' or its master was not found or no view engine supports...". I went debug mode and "Index" is not even the ViewName I'm passing, it's strange, but thank you for your help – HappySylveon Sep 20 '16 at 15:57
  • Yeah, I did think that. The problem is it doesn't know which view to use. You could hard code the view path in the child action. TBH, you really need to use a re-direct for this kind of thing. This is going to be difficult to maintain – Liam Sep 20 '16 at 16:00
0

I bet you are looking for RedirectToAction("ActionName", "ControllerName");

I have used the method below to get a string version of a view. Perhaps you can modify it to return a view based on your controller and view. The part where it returns IView.

protected string RenderPartialViewToString(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = ControllerContext.RouteData.GetRequiredString("action");

    ViewData.Model = model;

    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}
Ross Bush
  • 14,648
  • 2
  • 32
  • 55
0

I found a solution: https://stackoverflow.com/a/24475934/5485841

you can return a dummy view that has Html.RenderAction inside it. You can pass controller name and view name by ViewBag or Model.

Community
  • 1
  • 1
HappySylveon
  • 73
  • 2
  • 10