Problem:
Given this nested layout structure:
~/Views/Shared/_layoutBase.cshtml
~/Views/Shared/_layout.cshtml
Where _layoutBase.cshtml is the layout for _layout.cshtml.
Any sections defined in the layout files render their content fine in pages under ~/Views/...
However, for views in an area, the sections are never rendered.
Setup:
_layoutBase:
<script type="text/javascript">
#RenderSection("footerScripts", false)
</script>
</body>
</html>
_layout.cshtml:
#section footerScripts{
#RenderSection("footerScripts", false)
}
"content" view:
#section footerScripts{
$(function () {
SetFocusOnForm("CaptchaCode", "NextButton");
});
}
The content of section footerScripts never gets rendered in a view in an area. It does get rendered in a view that is under the ~/Views folder.
Area _ViewStart.cshtml:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Question:
Can you see anything wrong?!
I am unable to reproduce the problem. Here's my setup and steps I did.
Create a new ASP.NET MVC 3 application using the Internet Application Template
Add ~/Views/Shared/_LayoutBase.cshtml:
<!DOCTYPE html>
<html>
<body>
#RenderBody()
<script type="text/javascript">
#RenderSection("footerScripts", false)
</script>
</body>
</html>
Replace the contents of ~/Views/Shared/_Layout.cshtml with this:
#{
Layout = "~/Views/Shared/_LayoutBase.cshtml";
}
#section footerScripts{
#RenderSection("footerScripts", false)
}
#RenderBody()
Right click on the project and add an Admin area
Add a TestController to this admin area and add a corresponding ~/Areas/Admin/Views/Test/Index.cshtml view:
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#section footerScripts{
alert('ok');
}
Run the application and navigate to /admin/test/index
The alert is shown
The Reason Why:
I have got up this morning and saw the problem straight away:
I had the #section blocks in a Partial View. In MVC 3, that WON'T work!!
ARGH!
I really appreciate Darin's effort, that effectively provided proof that sections do work in Areas as expected. But the real cause was this.
I forgot they were in a Partial View, because I have a mvc 3 wizard that uses partial views for steps. It works so well and consistently, using ajax if javascript is available, that you forget what you are doing.
Please give Darin a vote, but this is the real answer.
Related
I am new to MVC 3 and have come accross the following scenario:
First let me explain how I have setup my application:
All post backs to the server use jquery ajax which which return a view from the controller that either appended or prepended or replace a targeted div.
The Scenario:
I have come to a point where I would like to upload images but unfortunately because of the jquery ajax posting I cannot get the values for an html in C# Request.Files. I know there are plugins out there to help out with this but I would like to do this myself so I have created an <iframe> which i then use a bit of javascript and post the form targeted to the iframe (old classic way of doing things):
function UploadImg(SACTION) {
alert(SACTION);
validatorform.action = SACTION;
validatorform.target = "fraImage";
validatorform.method = "POST";
validatorform.submit();
}
the SACTION parameter looks like this #Url.Action("UploadFile", "Response"). This all works well as it hits the controllers action method and I can then save the image:
[HttpPost]
public ActionResult UploadFile(string ArticleID)
{
ViewBag.PreviewImage = cFileUploads.UploadFile(ArticleID, Request.Files[0]);
return View("ImagePreview");
}
I would now like to return a view to the iframe (simply to preview the image and then do a couple of other things but this is besides the point)
The View for previewing the Image:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="">
<img alt="" src="#ViewBag.PreviewImage" />
</form>
</body>
</html>
The Problem:
Unfortunately when I return the View (ImagePreview.cshtml) in C# the whole page is refreshed, all I want is for the iFrame to be refreshed. How should I return the view from the controller?
Fiqured out the problem, I had a bit of javascript that was replacing the contents of a div that the iframe was sitting in ... (slap on my forehead). All working perfectly now :)
Will leave this question here just incase ..
This is my _Layout.cshtml
<html>
<head>
#RenderSection("Script", false)
</head>
...
</html>
This is a simple edit page edit.cshtml
#model Shop.Models.Product
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.EditorForModel()
and this is ~/Views/Shared/EditorTemplates/Product.cshtml
#model Shop.Models.Product
#section Script {
<script>alert("hello");</script>
}
...
#section Script{...} does not work in Product.cshtml because of EditorForModel. How can do it?
Sections work only in views, not in partials. An editor template is a special kind of partial. It's bad practice to put javascript in partials anyway, so I would simply declare the section in the Edit.cshtml view.
But if you very much insist on putting your scripts in the middle of your markup, since Razor doesn't support sections in partials, you could implement custom helpers to achieve that.
I have a view page
my view page
<div id="beReplaced">
#Ajax.ActionLink("please click on me to bring the partial view",
"PatrialViewToBeCalled",
new AjaxOptions()
{UpdateTargetId = "beReplaced",
InsertionMode = InsertionMode.InsertAfter,
HttpMethod="Get",
LoadingElementId = "prgress" })
</div>
i have a Controller
public PartialViewResult PatrialViewToBeCalled()
{
var customer = db.Customers.First();
return PartialView("PartialViewThatMustBeShow",customer);
}
but when i click on the generated link it brings me to a new page instead of
replacing or appending the partial view to the div tag.
What's the problem?
It could have been that you were missing the:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
In the main view. This tells the main view to recognize the ajax helper.
I found the solution. The problem was due to the corrupted unobtrusive-ajax.min.js file.
If you have jQuery loaded into your page, why not use the simple jquery get / load method to get the partial view ?
<div id="beReplaced">
please click on me to bring the partial view
</div>
Javascript
$("#lnk1").click(function(){
$.get('/controller/PatrialViewToBeCalled', function(data) {
$('#beReplaced').html(data);
});
});
If you are working with ASP .NET MVC 4 make sure that
#Scripts.Render("~/bundles/jquery")
is in the end of the body tag as well.
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
</body>
</html>
I've just been working on it for too long, thinking it did not work. Viewing the page source didn't show anything either.
Eventually, I found out it actually did work when I saw the successful requests in the console of Firebug. It only was showing it off screen. In the HTML tab of Firebug I finally found the output, even though it does not show up in the page source.
I am trying to render a section that is defined in _layout file from my custom area.
In my area I have the _ViewStart which points to the _layout in the root site.
The section that I am trying to use is in the head tag, but in my area it is put in the body.
Page that are rendered at the root level work fine.
~/Views/Shared/_Layout.cshtml
<head>
#RenderSection("header", true)
</head>
<body>
....
</body>
~/Areas/UserMedia/Views/_ViewStart.cshtml
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
~/Areas/UserMedia/Views/ManageProjectMedia.cshtml
#{
ViewBag.Title = "ManageProjectMedia";
}
#section header{
{
<!-- scripts and styles -->
}
<div>
... page content
</div>
On your question you pointed out a code sample whose path is ~/Views/_layout.cshtml and on your _ViewStart.cshtml file under your area, you have the following code :
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
I am sure you will find the seven difference here :)
Seven difference thing was a joke but anyway. Your _Layout.cshtml is sitting under ~/Views/ but you're referencing _Layout.cshtml which is under ~/Views/Shared/.
Consider fallowing declaration in view
#section sideaction
{
...
ViewBag.Title=Model.Title;
...
}
And in main layout i have this
<head>
<title> #ViewBag.Title</title>
....
...
</head>
..
...
<body>
..
#RenderSection("sideaction",required:false)
..
</body>
I am not getting title from view, i know that view will be processed before layout but i recognized that head section is processed before render section which is causing this problem.
One more thing , ViewBag.Title=Model.Title is just an example , the real Model is IEnumrable object and i am iterating and finding proper title. I can iterate in controller to find title but there is already iteration in view. For big collections one iteration is more efficient.
Any ideas?
You cannot set a ViewBag value in a section.
Use this:
#{
ViewBag.Title = Model.Title;
}
directly in the view to set a title.
Even it doesn't work, notice that the code has to be like this:
#section sideaction
{
#{
ViewBag.Title = Model.Title;
}
}
But as other people mentioned earlier, you can't do it this way inside a section.
You should put it directly inside your view:
#{
ViewBag.Title = Model.Title;
}
By the way, if you persist to change title of a page from inside a section, use javaScript/jQuery, e.g:
#section sideaction
{
<script type="text/javascript">
$(function () {
document.title = '#Model.Title';
});
</script>
}
Note: pay attention that it has to be '#Model.Title' (inside quotes).