Html.RenderPartial Works but Html.RenderAction not working (is blank) and no errors or exceptions - asp.net-mvc-4

Here is what i am trying
Layout
<!DOCTYPE html>
<html lang="en">
<head>
<title>WebApp Name</title>
<meta charset="utf-8" />
</head>
<body>
<div id="menuContainer">
#{Html.RenderPartial("~/Views/CustomPartials/_MainMenuPartial.cshtml");} #*Works*#
#*#{Html.RenderAction("GetMenuStructure", "Custom");}*# #*Not working*#
</div>
<div>
#RenderBody()
</div>
</body>
</html>
Controller and Action method
namespace Webappl.Controllers
{
[Authorize]
public class CustomController : Controller
{
[AllowAnonymous]
[ChildActionOnly]
public ActionResult GetMenuStructure()
{
return PartialView("~/Views/CustomPartials/_MainMenuPartial.cshtml");
}
}
}
_MainMenuPartial.cshtml
<ul id="ul_MainMenuStructure">
<li>Guest Pg1</li>
<li>Guest Pg2</li>
<li>Guest Pg3</li>
</ul>
The problem is
#{Html.RenderPartial("~/Views/CustomPartials/_MainMenuPartial.cshtml");}
Renders the contents of _MainMenuPartial.cshtml into the layout perfectly.
While
#{Html.RenderAction("GetMenuStructure", "Custom");}
Does nothing. No errors. No exceptions. Just blank. If i place a break-point at
return PartialView("~/Views/CustomPartials/_MainMenuPartial.cshtml");
The break-point is getting hit. I press F5 and it goes forward without any error/exceptions but menu structure does not get rendered in the layout. All I have is a blank
<div id="menuContainer">
</div>
in the final rendered page when I view it in the browser.
I need to do it through the action method for certain custom logic to be executed. Thats why a render partial is not sufficient.
I was not able to find similar behavior reported any where including stackoverflow. It could be bad binging/googling skills.
Some help will be so greatly appreciated. Banging my head on it for 3 days now.

I simply changed
#Html.RenderAction("X", "Y")
To
#Html.Action("X", "Y")

Related

How can I render section in a children Partial view?

The runtime&SDK I am using is the newest version .net 6
Here are three Partial views in _Layout.cshtml of my project: header.cshtml/aside.cshtml/footer.cshtml .
Why I speared them to three parts for there are so many codes for them that I have to speare for coding convenient.
Now I need to add a section to the header.cshtml. Here is my code:
<header>
///some other codes
#RenderSection("ProductNav", required: false)
</header>
No matter there is a section "ProductNav", after the program ran, the page will all be blank without any error.
I found that it seems I can not use the RenderSection in a children Partial view.
It seems there is another way by using the Html.Partial to achieve this.
However, it needs to convert the views that I want to add to string. That's so troublesome.
Is there an easy way can achieve this? Thank you.
You want to show navbar on partial pages, You use partial view to achieve this function, But user can't add css style in partial view directly.
My idea is you can create a External CSS file in wwwroot and use it in page whitch needs to load partial view.
I write a demo to demonstrate the feasibility of this idea.
Views/Shared/_header.cshtml
<h2>This is head Partial View H2</h2>
<p>This is head Partial View P</p>
wwwroot/css/header.css
h2 {
color: blue;
}
p {
color: red;
}
views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - EmptyNEt5MVc</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
//add the css file in here
#await RenderSectionAsync("Css", required: false)
</head>
//.........
View
#{
ViewData["Title"] = "Privacy Policy";
}
//use partial view
<partial name="_header" />
<h1>#ViewData["Title"]</h1>
<p1>Use this page to detail your site's privacy policy.</p1>
//reference css file
#section Css{
<link rel="stylesheet" href="~/css/header.css" />
}
Then you can see the `header partial view' load the css file successfully
=============================================
In fact, View Component is more suitable for navigation bar than Partial View, There is a document about View Component.

Navigating to different views without reloading entire page

I have a layout page that has one dropdown box. I created 3 views that will make use of this
layout. The value selected in the dropdown will be used in all 3 views created.
I have actionlinks used for navigation in the layout. Here is what I will like to achieve
Avoid reloading the entire page(layout) when I navigate from view to view since I want to keep
the dropdown value selected.
How can I achieve this such that it is only the content of the views that will be changing
when I navigate from page to page by clicking on the action links. The value of dropdown selected
must always remain the same unless changed by user
#model Company.Domain.Classes.Companyviewmodel
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title</title>
<link href="~/Content/Site.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
<div class="page">
#{
ViewBag.Title = "Project Status Maintenance";
}
<div id="MainContent1">
<div id="ProjID">
<label for="SelectProjID">Project:</label>
#Html.DropDownList("ddlprojects", Model.GetProjectInformationActive.ProjectsInfoSelectList, Model.GetProjectInformationActive.SelectedProject)
</div>
<ul>
<li class="pp1">#Html.ActionLink("Section1", "Index", "Home")</li>
<li class="pp2">#Html.ActionLink("Section2", "GetSection1Data", "Home")</li>
<li class="pp3">#Html.ActionLink("Section3", "GetSection2Data", "Home")</li>
</ul>
<hr class="divide" />
#RenderBody()
</div>
<footer>
<div class="ftrcontent">
<p>Got it !!</p>
</div>
</footer>
</div>
</body>
</html>
You can use ajax to do partial page loads. To start, give a css class to your links so that we can use those as our jQuery selectors when wiring up the ajax behavior.
#Html.ActionLink("Section1", "Index", "Home",null, new {#class="ajaxLink"})
#Html.ActionLink("Section2", "GetSection1Data", "Home", new {#class="ajaxLink"})
#Html.ActionLink("Section3", "GetSectionwData", "Home", new {#class="ajaxLink"})
Now you should have a container div in your page to which we will load the partial view content. May be your current view (index ?) , you can add a container view like this
<div id="pageContent"></div>
Now, let's listen to the click event on our links, get the content of the target page's via ajax and load to the container div. Assuming you have jQuery loaded to your page, we can use jQuery load() method.
$(function(){
//Load the first link's content on document ready
var firstLinkHref=$("a.ajaxLink").eq(0).attr("href");
$("#pageContent").load(firstLinkHref);
$("a.ajaxLink").click(function(e){
e.preventDefault();
$("#pageContent").load($(this).attr("href"));
});
});
Since we are loading partial page content to our placeholder div, we do not need to return the full markup(including layout) from your action methods, We just need to the partial view content. You may use the PartialView() method instead of View() method to achieve this.
public ActionResult GetSection1Data()
{
if(Request.IsAjaxRequest())
{
return PartialView();
}
return View();
}

Use controller result from other mvc project within solution

I've got a new solution that contains several project 'groups'. Each group contains a Cloud Project, a Web Role Project and a Test Project. All Web Role Projects are MVC4.
One of the Web Roles is the entry point for the visitor. Parts of what the visitor will see, should come from the other Web Roles from within the solution. I cannot get it working and after spending several hours googling, I still cannot solve it. Maybe anyone can be helpful on this issue.
For example, I need to fill the header content with data that I can get from one of the other Web Roles. Let's call that controller HeaderController. The controller in the main project (HomeController) looks like this:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
//var headerController = new Generic.HeaderFooterContainer.Controllers.HeaderController();
//var foo = headerController.Index().ExecuteResult();
//ViewBag.Header = headerController.;
return View();
}
In the comments are some things I've tried to debug some things.
Here's the page layout of the main project. The body is still empty, as this problem is just about the page header which could be placed as html from the ViewBag or ViewData or even with an own #section.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="headerHolder">
<div class="innertube">
<div id="header">
#ViewBag.Header
</div>
</div>
</div>
<div class="contentHolder">
<div class="innertube">
<div id="content">
#RenderBody()
</div>
</div>
</div>
<div class="footerHolder">
<div class="innertube">
<div id="footer">
</div>
</div>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bms")
#RenderSection("scripts", required: false)
</body>
</html>
The problem I face is that I just can't find out how I should make this work. How do I get the data in the header? A few things I've noticed are:
If I run the HeaderFooterContainer project in its dedicated solution, it works alright (I can get /Header and get the expected response displayed in the browser window)
If I run the Main project, I can see the home page, but if I ask for /Header, it can find the controller, but not the view. It's probably looking for the view in the main project although it is located in the HeaderFooterContainer project.

Add Dynamically Links to jQuery Mobile

I read a lot about how to add stuff dynamically in jquery mobile, but I couldn't figure out how to add links.
Currently my solution looks like this:
Add a new Page - with id (id="list-1")
Creating a Link for it (href="#list-1")
This solution works perfectly in static pages, but I want to do it dynamically. I have tried a lot with page() and stuff like that but nothing helped me.
My questions are:
How do I add dynamic links & pages?
Did I choose the right way to use ids & anchors (#list-1) as links or is there another solution for jquery mobile?
Let me know if you need more information
To add dynamic links, I have found the easiest way is to just have an event listener waiting for a click on those links. This event listener then saves any parameters you want to pass into the next page you are visiting. You pass the parameters from the list element to the event listener by just specifying parameters within each "li" element.
(create the HTML for a list dynamically & store it into list-1-html)
$("div#my-page div[data-role=content]").html(list-1-html);
$("div.list-1 ul").listview();
$("div.list-1 ul").listview('refresh');
Then your event listener would look something like:
$('#my-page').delegate('li', 'click', function() {
passedParameter = $(this).get(0).getAttribute('passed-parameter');
});
When jQuery Mobile loads your next page, you'll probably want to load this page dynamically and you'll have this passedParameter variable available to you. To load the page dynamically, just add a listener that waits for JQM to try to load the page:
$('[data-role=page]').live('pageshow',function(e, ui){
page_name = e.target.id;
if (page_name == 'my-page-2'){
(do something with passedParameter)
}
});
This is the workflow I use with jQuery Mobile and it has been working just fine. I'm guessing in future releases, though, that they'll build in some kind of support for passing dynamic parameters to pages.
Any new enhancement to the DOM should be done before the page initializes. But by default JQM automatically initializes the page once the page is load in browser.
Hence first you need to set autoInitializePage property to false and then call initializePage() method after the new page and links are add to the document. Hope this helps.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
$(document).bind("mobileinit", function(){
$.mobile.autoInitializePage = false;
});
</script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script>
$(document).ready(function() {
//add a link.
$("#page1 div[data-role='content']").append('Next Page');
//add a page.
$('body').append(' <div data-role="page" id="page2" data-title="next page"><header data-role="header" class="header"> <h5>Page 2</h5></header><div data-role="content"><h3>Good Morning...</h3>Back</div><footer data-role="footer" data-position="fixed"><h5>© All rights reserved</h5></footer></div>');
});
window.onload = function() {
$.mobile.initializePage();
};
</script>
</head>
<body>
<div data-role="page" id="page1">
<header data-role="header" class="header">
<h5>jQuery Mobile</h5>
</header>
<div data-role="content">
<form method="get" action="" data-transition="slideup">
<label for="email">Email:</label>
<input type="email" name="email" id="email" value=""/>
</form>
</div>
<footer data-role="footer" data-position="fixed"><h5>© All rights reserved</h5></footer>
</div>
</body>
</html>

Cannot create dijits via dojo.NodeList.instantiate

I am trying to get dijits to render using the dojo.NodeList.instantiate method, which takes existing HTML elements and turns them into dijits when the DOM has loaded.
The API reference for the instantiate method can be found here.
The following example, which calls the instantiate method in the dojo.addOnLoad method, should create a BorderContainer with two ContentPane instances, but the DIVs remain as they start out, and do not become dijits:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dijit Test</title>
<style type="text/css">
#import "dojoroot/dijit/themes/tundra/tundra.css";
#import "dojoroot/dojo/resources/dojo.css";
</style>
<script type="text/javascript" src="dojoroot/dojo/dojo.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");
dojo.addOnLoad(
function() {
dojo.query("#divOuter").instantiate(
dijit.layout.BorderContainer, {
design : 'sidebar',
gutters : false
}
);
dojo.query("#divMiddle").instantiate(
dijit.layout.ContentPane, {
region : 'center'
}
);
dojo.query("#divRight").instantiate(
dijit.layout.ContentPane, {
region : 'right',
splitter : true
}
);
}
);
</script>
</head>
<body>
<div id="divOuter" style="width:400px;height:300px">
<div id="divMiddle">Middle box</div>
<div id="divRight">Right box</div>
</div>
</body>
</html>
I have tried the above code in both Firefox 3.5 and Internet Explorer 7 and both fail to render the dijits. If I specify a standard HTML attribute in a property object (such as the style attribute), this style change appears correctly, indicating that the object is being read:
// The red border appears when using this example
dojo.query("#divRight").instantiate(
dijit.layout.ContentPane, {
region : 'right',
splitter : true,
style : 'border:1px solid red'
}
);
The following HTML (using dojoType and other property attributes) works fine - the BorderContainer and ContentPanes appear correctly in both browsers:
<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false"
style="width:400px;height:300px">
<div dojoType="dijit.layout.ContentPane" region="center">Middle box</div>
<div dojoType="dijit.layout.ContentPane" region="right" splitter="true"
style="width:200px;">Right box</div>
</div>
Please can anyone tell me why the instantiate example does not work?
I have done a lot of searching, but cannot seem to find anyone else with this issue, which may mean that I'm not using the instantiate method correctly!
Thanks.
You need to call startup on those dijits after they are instantiated. dojo.query.instantiate doesn't do it for you since it just creates the objects.
At the bottom of your onLoad function, add these:
dijit.byId('divOuter').startup();
dijit.byId('divMiddle').startup();
dijit.byId('divRight').startup();