I've created an area that will handle our some generic things across all our development products, just as log ins, HTML helpers, etc. Inside the area, I have a partial view that I'm attempting to reference outside of the area. I've registered the area with
public class Routes : AreaRegistration
{
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Common_default",
"Common/{controller}/{action}/{id}",
new {
controller = "Account",
action = "Index",
id = UrlParameter.Optional
});
}
public override string AreaName
{
get { return "MvcCommons"; }
}
}
And now in the regular project, I'm trying to reference a view in the MvcCommons area...
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>TestGrid</h2>
<% Html.RenderPartial("jQGridTable", ViewData.Model); %>
But I keep getting that the view isn't found. Before, while creating the MVC Commons project, I was getting view errors, but the errors told me that it looked in both the area folders and the default view folders. This time, I'm only getting the default folders. Is there any way to accomplish this?
Thanks everyone!
I haven't actually had to do this, but at a guess I would assume you should use Html.RenderAction() instead, something like Html.RenderAction("action", "controller", new { area = "Area", model = ViewData.Model }).
model will have to be replaced with the name of the action's parameters, but that should work.
edit this will require a controller and view setup for each action though.
An important thing to remember is that when using RenderPartial you use it in the context of the current action.
As your action isn't in an area it will only look in the View/ folder for the controller the action belongs to then the shared folder.
Any views you wish to share between areas and controllers and have available at the route should be the root View/Shared folder. Really if the view is callable as a partial like that there is probably little reason for it to belong to an area.
You can call into area when you want to render actions rather than partials - which then changes the context of the current action to the action you call into thereby allowing you to then return views within that area.
The Default ViewEngine looks for the Views inside the same area (or root) folders where the user control is referenced. If you want to create a custom way to use or store views, I suggest you to create a custom ViewEngine. Please take a look at this example: Implement Theme Folders using a Custom ViewEngine
Related
I have set up a menu-controller to drive the top menu links based on which other controller is being used. Each other controller has a separate nested master page for each of its views.
so, i have a menu-controller with several methods that return viewresults, one per each controller, or "section" of the site. So currently each of these methods has its own view to render the menu. but each view to render the menu is the same code, the only thing that changes is the logic in the controller methods based on which links to render.
is there any way to have all of these controller actions target the same view? since the view is the same for all?
thanks
Yes, that is a common practice.
return View("Menu");
Create a strongly typed view that takes a container specifying your menu content. Pass this as a parameter on your return statement.
var thisMenu = CreateMenuForThisRequest();
return View ("Menu", thisMenu);
it depends on what version of ASP MVC you're using; with MVC 2, you can create an ascx control and use RenderAction
in your view you'll put something like
Html.RenderAction("Menu", "Navigation");
and have a navigation controller with a Menu actionresult
public class NavigationController : Controller
{
[ChildActionOnly]
public ActionResult Menu()
{
Menu model;//your menu
return PartialView("YourMenuAscxControlName", model);
}
}
I think if you're using MVC 1, the MVC Future project has the RenderAction but i'm not sure.
For my menu I use the RenderAction method
I'm also using the ActionOutputCacheAttribute from Steve Sanderson
http://blog.stevensanderson.com/2008/10/15/partial-output-caching-in-aspnet-mvc/
you will greatly increase your site loading time with this caching
I currently have a MVC site that needs to have dynamic content on the header of every page.
I currently get the required data as normal in the controller and place it in a View Model. In the view, I take the data and stick the template parts in to the Viewbag and finally, on the main layout page, I take the Viewbag data and pass it to the partial which controls the header.
I've read that I shouldn't use Viewbag where possible, and the amount of times I pass the data round just doesn't feel right.
The only way I can think of to improve this is to create a section on the main layout, and then put the partial/data in the section of the view - however, there are ~30 pages and this again doesn't feel like the correct route.
Is there a better way to do this/what are the best practices for taking dynamic data that has to go to the main view?
You can do this with Child Actions. You can reuse this action and even include it in the _Layout page.
Here's a child action to display some header info. It is marked ChildActionOnly so it can only be called within another view. It also takes advantage of OutputCache to save a result for 5 minutes.
[ChildActionOnly]
[OutputCache(Duration = 5 * 60)]
public ActionResult Header(string section)
{
var info = new HeaderInfo
{
Section = section,
Today = DateTime.Now
};
return PartialView("_header", info);
}
_header.cshtml
#model HeaderInfo
<div>
<span>#Model.Section</span>
<span>#Model.Today.ToLongTimeString()</span>
</div>
Then use this in a view or layout with Html.Action() or .RenderAction().
#Html.Action("Header", "Home", new { section = "Cake" })
// or
#{Html.RenderAction("Header", "Home", new { section = "Pie" });}
You can specify a section inside your layout then conditionally render if present in the view.
_Layout.cshtml
#RenderSection("header", required: false)
main view
#section header {
#{Html.RenderAction("Header", "Home", new { section = "Cake" })}
}
So my current (and I believe this is the default way) to use _ViewStart.cshtml is to do this:
Layout = "~/Views/_SomeSideMenu.cshtml";
Now my sidemenu is a bit complicated so it requires a controller. But I cannot figure out how to call a controller action for the ViewStart and let it return the PartialPage for it.
My current workaround involves using #Html.Action() in the _SomeSideMenu.cshtml file and fill TempData with the things I need.
Normally I would want to put that data in the ViewBag or Model, but these are not available since the Html.Action does not return the _SomeSideMenu.cshtml.
How would one go about calling the controller action to return the PartialPage that is found in the _ViewStart page?
Actually, you cannot do this in the ViewStart file. ViewStart is a file that can store common functionality related to all the views. These pages can also be nested, so if you have multiple controllers, each controller’s views can have their own ViewStart page.
You should add your sidemenu into a Layout page. You could add some conditions to have this output into layout page. For sample, jere, we have an action filter which add a key into ViewBag and we use this key to have a state for a sidemenu (state like open or close and position in left or right).
You also could change your default layout page in your view just doing what the ViewStart page does, chaging the Layout property.
Layout = "~/Views/Shared/CustomLayoutPage.cshtml";
I've converted old MVC2 project to MVC3. Now I have .aspx views along with razor .cshtml.
Let's say I have a view associated with controller (HomeController, Index action and ~\Views\Home\Index.aspx) and at the same time I still have absolutely different ~\Views\Shared\Index.aspx.
Normally when Index Action calls View() it renders ~\Views\Home\Index.aspx. But if I convert the view into razor view, the same action instead of rendering ~\Views\Home\Index.cshtml calls
~\Views\Shared\Index.aspx.
So I guess MVC gives priority to .aspx pages rather to .cshtml. Maybe I need to change something in web.config files, because now I have to explicitly tell it which view to get:
View("~\Views\Home\Index.cshtml")
Even if I drop the extension View("~\Views\Home\Index") it will still call the shared .aspx view, although I have the right path. Strange isn't it?
The problem you are having is the default priority of MVC views. Here is the default:
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
As you can see, it favors all aspx/ascx files, even in the shared directory, before similar razor views.
One solution is to Get MVC Razor favor .cshtml over .aspx, however this solution does NOT reassociated the aspx/ascx files. So you'd need something like:
protected void Application_Start()
{
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
ViewEngines.Engines.Add(new WebFormViewEngine());
}
i got stack on my project the problem is after adding new controller class and views for the actions unable to link the views with existing views
*
The resource cannot be found
.*
i have home and account controller classes which work well and i add new controller class users and i have to action methods index and adduser both have view but anytime when i try to retrieve view from the new controller class it dosnt found the pages.
eg <%= Html.ActionLink("users", "Index", "users")%> please help !!!
have you created views?
Guideline:
create controller controller_nameController
create action public actionresult action_name(){return View();}
create views Hit ctrl+m, ctrl+v or right click on the action whose view you would like to create.
4. check if you really have created a view named action_name in controller_name folder
Then you can create links: ("to display text", "action name", "controller name")
Hope this helps.