Mvc doesn't render nested master page in Umbraco - asp.net-mvc

I have a master template that calls "RenderBody()" and a "OneIn" template that is a child under the Master page. I also call the RenderBody() function in the OneIn template but then it gives me this error:
The file "~/Views/OneIn.cshtml" cannot be requested directly because it calls the "RenderSection" method.
The "RenderSection" was i actually "renderbody" i was just trying something new, and it didn't work either
Nest Path:
Master
-> Homepage
-> OneIn
-> One Column Page
I also have these lines on code on top of all pages:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = "ParentPageName.cshtml";
}

It seems like you have an action method that is trying to return the "onein" layout directly, which can't happen if you are calling RenderSection or RenderBody inside of it. Thank of any View that has RenderSection/Body in it as an abstract class that can't be new-ed up but instead have to be inherited!

Yes, I found this as well which is a bit jarring when coming from Master Templates. You can have many levels of template inheritance, but your content pages can only use templates that are at the lowest level. That would be One Column Page in your example.

Related

Problems returning PartialViews from controller

I am using MVC 4 and I have some areas in my project and some Views and Partial Views within each area:
Areas
AdminArea => one area and so on
Views
Customer
Customer.cshtml => my View
_CustomerDetails.cshtml => my partial View
In my controller, CustomerController I have the following code that fails:
return PartialView("_CustomerDetails", model) => fails to find my partial view.
However, if I call
return PartialView("~/Areas/AdminArea/Views/Customer/_CustomerDetails.cshtml", model)
the code executes successfully.
My Views (not partial views) all work ok. I even have some some partial views (also in the same area) that render ok without specifying the full path, but for some reason, for the most of them the above code fails in constructor saying that:
The partial view '_CustomerDetails' was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Customer/_CustomerDetails.cshtml a.s.o. ... => and is searching in global not in Admin area.
Is there any way to fix this problem without having to specify the full path to my PartialViews in code? (like passing area="Admin" like I do in the .cshtml file).
I am not using any custom ViewEngine and I have called AreaRegistration.RegisterAllAreas() in Global.asax.cs.
Thanks,
Tamash
I am really sorry for even posting this question:
The call from the controller worked fine, but the problem was that I was calling from javascript to get the PartialView through an action and I didn't specify the full name for that action. That's why the partial view wasn't returned since the method responsible for returning it wasn't being called at all.
Sorry about that: the code is a bit complex and I got lost in details around Ajax calls.
seems weird, try adding a view from controller action method i.e right click action method in controller, add view, make a view a partial view and see where it adds it.. check if it is the same location as you are putting, if not there is some structure prob/bug.

Creating a navigation for entire website

HI I am just learning asp.net mvc 3 and I am tryng to create a common menu for my entire application.I understand I can do that in _Layout.cshtml file witch is the default template for every page.
Now I have looked into sections for adding a template insite _Layout.cshtml but from what I can gather I need to define the section in every view.
I already have the logic for accesing the data defined in a separate class.All I need is to call the method witch will return a Dictionary<string , List<string>> , and then display the data by looping into it.
Aldo I could probably do this directly inside the Index.cshtml file by using the razor syntax I believe there must be a better way
So is there a way to create a template that can then bee added inside the _Layout.cshtml?
Creating a section for the menu on each view could work but I think another approach could be easier to mantain. On your layout itself use #Html.Partial to render your menu. Then on that partial view you could have all kinds of operations, such as database access, in one single spot.
Here is an article on how to do exactly this:
http://techbrij.com/981/role-based-menu-asp-net-mvc
Was just looking into something similar. Hopefully partial views are your answer, this is a template you can re use and stick on any page. Information found here.

Can a controller influence the _layout.cshtml file?

I'm stuck! I'm under the impression that the _layout.cshtml file is used for MasterPage-like content. Everything there is rendered on every page. Naturally, I want to write the code for rendering my sidebar menu in that file.
I want to dynamically display a list of Categories from my DB, but I'm having a problem with passing the actual model of categories to Layout.cshtml since it seems no controller actually touches it.
Any suggestions?
Otherwise please tell me how to approach this problem. I've been wracking my brain for the past three days and still no elegant solution.
I need to:
Dynamically fetch a list of Categories from the DB.
Display this list of Categories on every single view. (Hence the use of _layout.cshtml)
Elegantly handle each different categories click.
I'm at my wits end. :P How would you solve this?
_layout.cshtml
#if(isSectionDefined("Categories"))
{
<div id="sidebar">
#RenderSection("Categories", required: false )
</div>
}
index.cshtml
#section Categories {
<ul>
<li>Category One</li>
<li>Category Two</li>
<li>Category Three</li>
</ul>
}
see this : http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx
Any viewmodel that you pass to your view is automatically available within your master page. If you do not use RenderAction/Action which is the best approach, then you must create the necessary master page data in every action and add it to viewdata - either by having a common base class for your strongly typed viewmodel that contains all master page data or by using the viewdata dictionary.
I would strongly recommend that you go down the html.action approach though. In this way, you have a totally separate controller action for dealing with your list of categories. This action can retrieve the neccesary category data and return the categorylist usercontrol as a partialview and you will not have to worry about polluting all your other actions with this data.
As I see it, ViewData (and its relatives like ViewBag, Model, etc.) is meant for the specific current view. Your _Layout.cshtml is not specific to the current view; and it would be awkward if EVERY controller would have to pass the categories data in addition to whatever else data it needs to pass for the view.
Instead, what I do, is provide a static method in one of my helper classes that retrieves the categories from the DB. I also do some caching there, so that I do not have to hit the DB on every single request. The _Layout.cshtml then simply calls this static method. Simple and elegant.
If you wish, you can bring this out to a partial view, make it a helper method, whatever.
One note of caution though - my custom error view also uses the same _Layout.cshtml, and if the DB goes down, you get an exception trying to display the exception. ASP.NET MVC is smart enough to detect this and abort processing, but you're left with a nondescript default error page. What I did was to place try...catch statements around these dangerous calls, which quietly ignore the exception if the current page is the error view.
I've achieved something similar by having my ViewModels implement an Interface which has members that contain the menu data. In my action method I set that data. Then in my view I check to see if my view-model implements that inteface, pull the menu data out and render the menu (in a partial view actually)

Programmatically determine name of Master Page from aspx file

I'm writing a custom WebFormViewEngine and i would like to figure out the name of the Master Page file specified in the view's aspx file when the WebFormViewEngine.FindView method is called.
My end goal is to determine the name of the desired master page file so that i can use a master page file of the same name in a different directory to render the view.
So the challenge is that i have the file path of the view, but before the view is rendered i want to determine the name of the master page file.
I can open the file and search for MasterPageFile="%", but i'm hoping there's a better way to do this.
Thanks.
Master page lookups work differently than what you think. In MVC WebForms view engine there are basically two ways of specifying the master page:
In the <%# Page %> directive of the view page.
This method is not actually MVC-specific, it depends on the functionality built into WebForms control trees. You need to provide the full path and this value never gets looked at by the MVC pipeline, because it only gets set and evaluated once the view starts executing (which happens after WebFormViewEngine.FindView).
In your action method ViewResult: return View("Index", "MyCustomMaster")
You can override the master page from your controller. In this case you can specify just the Master View name or the full path to the master file. This value does get passed into WebFormViewEngine.FindView and it overrides whatever might be specified in the view itself.
If you always only use #2, then the values will always go through WebFormViewEngine.FindView. However if you also use #1, then you'll basically have to do the same thing that MVC does to enable #2: write your own custom Page class:
public class MyViewPage : System.Web.Mvc.ViewPage {
protected override void OnPreInit(EventArgs e) {
base.OnPreInit(e);
// you might not need the following, but perhaps it would be useful to
// differentiate between #1 and #2
bool masterOverridenInController = !String.IsNullOrEmpty(MasterLocation);
string currentPathToMaster = MasterPageFile;
// change currentPathToMaster any way you like
MasterPageFile = currentPathToMaster;
}
}

Where to apply logic for a sidebar control in ASP.NET MVC

Take the example of wanting to have a "Latest news items" sidebar on every page of your ASP.NET MVC web site. I have a NewsItemController which is fine for pages dedicating their attention to NewsItems. What about having a news sidebar appear on the HomeController for the home page though? Or any other controller for that matter?
My first instinct is to put the logic for selecting top 5 NewsItems in a user control which is then called in the Master Page. That way every page gets a news sidebar without having to contaminate any of the other controllers with NewsItem logic. This then means putting logic in what I understood to be the presentation layer which would normally go in a Controller.
I can think of about half a dozen different ways to approach it but none of them seem 'right' in terms of separation of concerns and other related buzz-words.
I think you should consider putting it in your master page. Your controller can gather data (asynchronously, of course), store it in a nice ViewModel property for your view (or in TempData) and then you can call RenderPartial() in your master page to render the data.
The keeps everything "separate"
http://eduncan911.com/blog/html-renderaction-for-asp-net-mvc-1-0.aspx
This seems to address the question - even using the instance of a sidebar - but using a feature not included with MVC 1 by default.
http://blogs.intesoft.net/post/2009/02/renderaction-versus-renderpartial-aspnet-mvc.aspx
This also indicates the answer lies in RenderAction.
For anyone else interested, here's how I ended up doing it. Note you'll need to the MVC Futures assembly for RenderAction.
Basically you'd have something like this in your controller:
public class PostController
{
//...
public ActionResult SidebarBox()
{
// I use a repository pattern to get records
// Just replace it with whatever you use
return View(repoArticles.GetAllArticles().Take(5).ToList());
}
//...
}
Then create a partial view for SidebarBox with the content you want displayed, and in your Master Page (or wherever you want to display it) you'd use:
<% Html.RenderAction<PostController>(c => c.SidebarBox()); %>
Not so hard after all.
You can create a user control (.ascx) and then call RenderPartial().
Design a method in your controller with JsonResult as return type. Use it along with jQuery.
Use RenderAction() as suggested by elsewhere.
News section with ASP.NET MVC

Resources