276

Is it possible to display a view from another controller?

Say for example I have a CategoriesController and a Category/NotFound.aspx view. While in the CategoriesController, I can easly return View("NotFound").

Now say I have a ProductsController and an action and view to add a product. However, this action requires that we have a Category to add the Product to. For example, Products/Add/?catid=10.

If I am not able to find the Category based on catid, I want to show the NotFound view from the Categories controller instead of creating a CategoryNotFound view under the Products controller.

Is this possible or am I structuring things in the wrong way? Is there a good way to do this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dtc
  • 10,136
  • 16
  • 78
  • 104

7 Answers7

326

Yes. By default, ASP.NET MVC checks first in \Views\[Controller_Dir]\, but after that, if it doesn't find the view, it checks in \Views\Shared.

The shared directory is there specifically to share Views across multiple controllers. Just add your View to the Shared subdirectory and you're good to go.

If you do return View("~/Views/Wherever/SomeDir/MyView.aspx") You can return any View you'd like.

womp
  • 115,835
  • 26
  • 236
  • 269
  • Thanks, this sounds like the solution I should be using. I still wonder if it is possible to display a View from another controller though. I'm guessing this violates some rule in MVC? – dtc May 18 '09 at 21:29
  • 1
    In the situation you describe above, yes, you should be using the Shared folder. – Jon May 18 '09 at 21:58
  • 75
    Yep, that is also possible. If you do return View("~/Views/Wherever/SomeDir/MyView.aspx") You can return any View you'd like. This doesn't violate any particular rule per se, however, ASP.Net MVC is all about "convention over congfiguration". In other words, the framework is built to operate automatically using certain conventions, and you should utilize it where possible. – womp May 18 '09 at 22:03
  • 2
    Thanks for the explaination. I didn't know Views could be called like that. The Shared directory of course works perfectly :) – dtc May 19 '09 at 20:28
  • 2
    I wasn't in a Controller, so I had to use `new ViewResult { ViewName = "~/Views/Error/Unauthorised.cshtml" };` and it worked – Nacht Jul 18 '17 at 01:55
  • 1
    This solution leaves the URL unchanged (the view which will be rendered won't correspond to the displayed URL in the browser)! – Mr. L Dec 12 '19 at 08:15
173

You can use:

return View("../Category/NotFound", model);

It was tested in ASP.NET MVC 3, but should also work in ASP.NET MVC 2.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Guillaume86
  • 14,341
  • 4
  • 53
  • 53
73

Yes its possible. Return a RedirectToAction() method like this:

return RedirectToAction("ActionOrViewName", "ControllerName");
doncadavona
  • 7,162
  • 9
  • 41
  • 54
  • 1
    I believe this should go as RedirectToAction("ActionOrView", "Controller", null) as otherwise second paramater is routeValues – Zoran P. Dec 20 '14 at 08:11
  • But in this case, you have to actually write the action in the controller, unlike with the View solution. – tobbenb3 Mar 05 '19 at 17:13
  • @tobbenb3 That's a much better solution as opposed to hardcoding a result. Either way you shouldn't be passing in a path string. – perustaja Feb 14 '20 at 22:54
35

Have you tried RedirectToAction?

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
Paul Johnson
  • 1,417
  • 1
  • 17
  • 26
  • 1
    I would say that this is the MVC for anyone that doesn't want the view int he shared folders, note that for all other solutions (such as using direct paths) anyone trying to re-factor the views will not have to take in mind that it is also being used in another controller, resulting in unpredictable behavior – yoel halb Dec 04 '12 at 18:10
  • 4
    how about without redirecting? – Luckyy Nov 07 '13 at 10:58
  • way better solution than moving the view to shared folders – juFo Apr 10 '14 at 09:22
  • This solution requires action on controller, View(directPath) renders output without any action. When you add an action, you need to think to hide it from direct access via url, it will generate step in browser history etc. But yes, it's my way to go. – Jan Zahradník Apr 17 '14 at 18:55
  • 3
    RedirectToAction sends a 302 response code to the browser. That is not appropriate when you are trying to show a 404 not found page. That is, this solution appears to work but will confuse search engines. – NightOwl888 Aug 23 '14 at 13:30
  • Couldn't you modify the Response.StatusCode to the proper status code in the view? Or would the status code be read by the search engine before this modification take place? – nulltron Jan 03 '19 at 21:43
  • @NightOwl888 good point about the 404. I'm not sure if he would want a 404 status though since he has a page for it. Although, its an interesting point. I would say if the categories are dynamic then maybe 404 is not a good idea? This maybe like having a 404 if you searched for keywords that yielded no results. – Paul Johnson Feb 12 '19 at 13:09
  • @NullReff - No, each request only returns a single HTTP response. In the case of `RedirectToAction`, the first request will return a 302, instructing the browser to do a *second* request for the URL (strictly speaking, the browser doesn't have to follow this instruction, it is out of your control). If a search engine *does* follow a 302 redirect to a 404 not found response, this is a confusing set of instructions, and a wasteful and unnecessary round trip. – NightOwl888 Feb 12 '19 at 13:26
  • @PaulJohnson - There would really be nothing wrong with displaying a custom page and also providing a 404 status code. The HTTP status and the page that is displayed are independent. However, making the status 302 when you meant to provide a 404 is a wasteful approach. If you want your application to show a 404 for a certain URL, you should *route* to that action, not *redirect* there. That is, make one round trip, not two. – NightOwl888 Feb 12 '19 at 13:29
24

Yes, you can. Return an Action like this :

return RedirectToAction("View", "Name of Controller");

An example:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees");

This approach will call the GET method

Also you could pass values to action like this:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees", new {id = id.ToString(), viewtype = "extended" });
anil shrestha
  • 2,136
  • 2
  • 12
  • 26
Ignacio Chiazzo
  • 947
  • 11
  • 25
5

You can also call any controller from JavaScript/jQuery. Say you have a controller returning 404 or some other usercontrol/page. Then, on some action, from your client code, you can call some address that will fire your controller and return the result in HTML format your client code can take this returned result and put it wherever you want in you your page...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marko
  • 1,874
  • 1
  • 21
  • 36
  • I did not know that. That sounds like it's something I might use in the future. Yes, mvc rocks :) – dtc May 20 '09 at 18:33
1

With this code you can obtain any controller:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, 
controller);
Renan Araújo
  • 3,533
  • 11
  • 39
  • 49
Yair GR
  • 29
  • 3
  • Translation: With this code you can obtain any controller: [code], Regards, – Robert Columbia Sep 07 '18 at 02:26
  • 3
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Nic3500 Sep 07 '18 at 03:51