Access non-area view from within controller in an area - asp.net-mvc

I worked on a project that until recently had no need for areas. Now that I've added an area (TemporaryUser) I'm having difficulty making use of a shared _Error view that is not within its own area.
I know I could just create another area, call it "master" or something, and access its views through typical routing, however it would mean reorganising quite a few files and changing paths.
Is there a way to return a view that is not in an area from within a controller action, that is?
return View("~/Views/Shared/_Error.cshtml", ResponseMessages.TEMP_USER_BATCH_NOT_EXIST);
Where this is in {area}/{controller}/{action} but as you can see the view I'd like to use is in the default shared folder given in MVC 4.

Related

How to use MVC Controllers for Layours in Sitecore?

I'm very new to sitecore and just started learning sitecore over at a dev-course held here in town.
The course is WebForms-focused, and since that's not my "patter of choice" I thought I would see how far I can get using MVC in Sitecore.
However, I have a slight problem. I have noticed how there are Controller Renderers, but and how they are bound to a Controller and such. but how about using a Controller for a Layout?
Lets say I have a layout, that for instance might statically render a menu on the top of the site. Then in this case I would like to avoid having a huge amount of code in my view for rendering the menu-items. Instead I would like to have build and populate a custom view model with the menu items and then simply pass down the model to the view and iterate through my menu items within my model.
But I just cant find a way of how to create a controller for a Layout. Any ideas?
Actually, this is possible, you can create a model deriving out of RenderingModel class or implement IRenderingModel interface and assign it to any MVC rendering or layout in Sitecore. Model object will be instantiated by the Sitecore's GetModel pipeline defined in Sitecore.Mvc.Config file.
See Here
Another way to handle this scenario is to create a Menu view rendering and then insert into a placeholder defined within the layout possibly a header placeholder. This can be statically assigned via standard values.
Kevin is right, thats not possible. Actually, Sitecore uses the layout to recognize a view extension and handle the request with MVC (TransferMvcLayout processor in the httpRequestBegin pipeline).
You should consider an approach where you add a placeholder in your layout:
#Html.Sitecore().Placeholder("menu-placeholder")
Then add a Menu Controller Rendering to that placeholder. That way you can utilize the rendering cache as well.
I don't think this is possible. But you can create a Razor view as layout, which works same as a View Rendering. Just just need to specify the path to the Razor view in the Path field and insert a model. In the model you could have simple property, which loads your menu items from whereever you want:
public class MyViewModel
{
public IEnumerable<MenuItem> MenuItems
{
return MyMenuUtil.LoadMenuItems();
}
}
This avoids lot of code in the Razor view and also in the model.

Dynamically Rewriting the Razor Nested Layout Stack

I'm trying to add theme support to an application by using a custom view engine to dynamically add view search locations based on the theme associated with the current HttpContext.
This works really well for raw views as the locations are searched in order and if a view exists in the relevant theme folder, that is used otherwise it falls back the the default view in the standard location.
However, we make extensive use of nested layouts, typically at least three levels deep (so rewriting just the layout of the current view will not work), and Razor layouts do not use the view engine to resolve as they are typically specified as a full path from root of the application.
For example, if I have the following in a view:
#{ Layout = "~Views/Shared/OneColumn.cshtml"; }
I know I could implement something like this:
#{ Layout = ThemeHelper.GetLayoutPath("OneColumn.cshtml"); }
But what I would much rather do, if possible, is:
#{ Layout = "OneColumn.cshtml"; }
And have the view engine, or any extensibility point really, resolve that to the best match using the same rules as are applied for the main view.
Any ideas?

MVC Project Design, pros and cons of re-using Partial Views

I have a question for the pros and cons on how reusable partial views should be used in a project.
In the first example, I have a layout that is used between all the views. In the layout, I have a partial view that gets called using Html.RenderAction("Index", "Header"). This header changes based on if the user is logged in or not and it renders on every view.
In the second example, I have a static layout that is used between all the views. However, in this layout there are no partial views being called. The Header partial view is being called on each view and basically does the same thing as the first example (changes based on if a user is logged in or not, etc.)
Which approach is better, is one way or another the correct way? Pros and cons of each?
One of the main ideas behind asp.net-mvc is to not reuse code. So with this in mind, you should have your Header code in your _Layout file. This way it is not being retyped in every View, and if you needed to remove it or add route values, etc you do not have to update every View that has it.
An example of this is the _LogOnPartial that is in a default project. In the _Layout it is called by #Html.Partial("_LogOnPartial"), and the _LogOnPartial view contains a logic statement that either displays LogOn or Register or Welcome back....

Asp.net MVC - Can I load a view from a different view folder?

In my app I have a need to load the same view from two different controllers without placing the view in the shared views directory.
Basically I have this folder structure
Controllers
EventsController.cs
SearchController.cs
Views
Events
Preview.aspx
Search
basically picture it much the same as here on stack overflow. You get a preview of a bunch of questions under the questions link, but you also get an identically formatted page when you do a search in the search bar. The views and viewmodels are presumably identical.
Since the view I need for search is exactly the same as the view I need for events, I'd like to reuse the same view. I would however like to avoid using the shared directory for this specific view.
So my two part question is ---
Is this possible, and if so how?
Is this bad practice?
Yes, you can. Simply return View("~/Views/Events/Preview.aspx").
However, i would advise against it for a number of reasons. The biggest being that this will be non-obvious to anyone trying to modify the code later (maybe even you) and might lead to potential errors.
A better approach might be to create a "Shared" view, or a shared partial view. My preference would be a shared partial view, then in your non-shared view render the partial view functionality you want.
It's possible.
I am not sure if you are using strong-typed views. But suppose it is, then it is a bit weird for me that you have Event search & Search with same View Model. Possibly separate them with two different view models and view would be better IMHO. Moreover, if you specify the name of view to load in controller, it is somehow considered to be coupling view and controller and it certainly not a good idea.

Is menu link suppression a responsibility of the view or the controller?

In ASP.NET MVC, I am building a site with the requirement that the main menu (appearing on every page) should remove the hyperlink for an entry (leaving just the text) if the current page is the one linked to.
The menu html is defined in the master page for the site, but is currently populated from the ViewData passed by the controller. This is set up so that the base controller defines a dictionary of link objects, then the actions on the controllers grab the relevant entry out of the dictionary, set the address to empty. The base controller then passes it to the view as an IEnumerable<>.
However, looking at it with a critical eye, it feels more like something the view should have sole responsibility for: the menu doesn't change, so the controller feels like it's butting in where it shouldn't. My only slight reservation is that the View would be knowledgable about what the current page is, which feels like more of a controller concern.
I've been arguing around in circles in my head for a while now, so I'd like some other opinions on this. I would have thought this would be a fairly common scenario?
(One final clarification to my problem: the main menu links are to "landing pages" of the various areas of the site (basically the Index action of all the controllers), and once you've navigated into the area and are off the landing page, all entries in the menu will be linked)
We might like to think of views as being very dumb in that their only task is to turn the data provided by the controller into something that the client can parse and display.
However in fact most views (certainly all the examples of ASP.NET-MVC I've seen) considerable application logic is embodied in the views in that its the view which dictates how the user can navigate around the application. If it were not for the view including code to create clickable links, images and buttons we wouldn't have much of an application.
Hence a view having a menu which it controls the content of is not contrary to the spirit of the separation of concerns. OTH, a controller providing some from of list to be turned into a menu is also acceptable. In that case you would expect the controller to dictate which members of the menu should be available to click, the views role in this scenario would be to carry out the wishes of the controller.
I'd go for creating a controller for menu display. Putting too much logic into the view makes it harder to maintain, I think.
Not showing the user manu entries that he can't use, for some reasons, is a part of your application logic rather then the view itself. I always try to treat view as a dumb part of code that just does what's needed - loops, basic display-related ifs, such things.
Also passing just enough important data to the view might make the application easier to test.
I agree with AWJones that it's a bit grey area, but imho if the view should be responsible for how something is presented and the controller for what that something is, then the contents of the menu are in the domain of the controller.
I kind of feel the "suppression" of parts of the menu should be hidden from the view (and the end user) entirely - the view should get what it needs and no more.

Resources