Reputation: 1619
I would like to render the "scripts" section of the .cshtml view inside the controller as a string. Is this possible?
What I actually want to do is get the scripts with a separate ajax call and then run eval on the script after loading the html of the view also with ajax.
I've tried looking for related topics but haven't come up with anything relevant. Some related answers fool around with HtmlHelper.ViewContext.HttpContext.Items[""]
but I'm unsure how to use it.
What I want is something like this: string scripts = GetScriptsForView(action, controller);
which returns the section used in the view like this: @section Scripts {
To clarify (edit):
I'm trying to replace the "RenderBody()" of the layout page with ajax calls, so that I don't have to load the layout containing the static header every time.
I have managed to replace all <a>
-tags with ajax calls replacing the <div>
containing the view, but am unable to get the javascripts working.
I could remove the @section scripts {
from the cshtml-files and let the script tag get loaded with the html view. The problem with this is that if I reload the page it calls the scripts for that view before calling the scripts of the layout page, resulting in errors. Therefore I wish to load the scripts separately.
Upvotes: 4
Views: 2668
Reputation: 637
As per my understanding I guess you are looking for load the page via Ajax without reloading the entire page.
Did you check the Kool Swap Jquery plugin? Hope this will match your requirement.
Upvotes: 0
Reputation: 125227
While you can load sections and contents in separate requests (see example 1), but you don't need to do that. Instead:
You can have different Layout
pages for different purposes and dynamically decide which layout to use for the view. For example a full layout page for normal requests and a simple layout page without headers and footers for ajax requests (see example 2).
You can decide dynamically about the layout page in _ViewStart.cstml
or in the controller, based on different request parameters, like Request.Headers
, Request.QueryString
, Request.IsAjaxRequest
, etc.
Here are some useful notes about the layout, section, view and partial view which may help you to handle the case:
Specify Layout in return View() - When returning a View
you can specify the layout for the view. For example return View("Index", masterName: "_SomeLaypout")
. You can have some logic to dynamically decide about the layout name.
Specify Layout in _LayoutStart.cshtml - When returning a View
, you can specify the Layout
in _ViewStart.cshtml
file, for example @{ Layout = "_Layout"; }
. You can have some logic to dynamically decide about the layout name.
Render content without Layout - When return a view using PartialView()
method, it will render the whole content of the view without any layout or without rendering any section. It's equivalent to using return View and setting Layout
to null, in _ViewStart.cshtml)
Render Section without any Content - You can have a layout having just a RenderSection
method. Then if you return a view using that layout, it just renders the specified section of that view and will ignore the contents.
Scripts with/without Section - Considering above options, when you put scripts in the script tag without putting in a Section
, you guarantee they will be returned as part of the result, regardless of calling return View
or return PartialView
or having or not having Layout
. So in some cases you may want to put scripts without sections. In this case, when you load the partial view using ajax call, it contains the content as well as scripts of the partial view.
In some cases you may want to have some common content/scripts even for partial views, in such cases you can use Section, also have a Layout page which renders the section and contains common things that you want to have in all partial view. In this case you need to return the partial view using return View
and specify that specific layout page.
The following example shows how you can send an ajax request to get content and send an ajax request to get scripts section.
Please note, I don't recommend using different requests for getting content or getting scripts separately and this example is just for learning purpose to show you what you can do with
Layout
pages and_ViewStart
.
To do so, follow these steps:
Change the _ViewStart.cshtml
content to:
@{
if(Request.QueryString["Layout"]=="_Body")
{
//Just content of the page, without layout or any section
Layout = null;
}
else if (Request.QueryString["Layout"] == "_Script")
{
//Just script section
Layout = "~/Views/Shared/_Script.cshtml";
}
else
{
//Everything, layout, content, section
Layout = "~/Views/Shared/_Layout.cshtml";
}
}
Note: Instead of a Request.QueryString
, you can easily rely on a Request.Header
or Request.IsAjaxRequest()
or ... base on your requirement.
Then just for _Script
, add a new layout page named _script.cshtml
having the following content:
@RenderSection("scripts", required: false)
Then:
To get the script section, send a normal ajax request and add the following query string: Layout=_Script
.
To get the content without script section, send a normal ajax request and add the following query string: Layout=_Body
.
To get the whole content, send a normal ajax request without specifying any Layout query string.
For example, assuming you have a Sample
action in Home
controller:
[HttpGet]
public ActionResult Sample()
{
return View();
}
Which returns the following Sample.cshtml
view:
<div id="div1" style="border:1px solid #000000;">
some content
</div>
@section scripts {
<script>
$(function () {
alert('Hi');
});
</script>
}
In client side, to get the script section:
<button id="button1">Get Sample Content</button>
<script>
$(function () {
$('#button1').click(function () {
$.ajax({
url: '/home/sample',
data: { Layout: '_Script' },
type: 'GET',
cache: false,
success: function (data) { alert(data); },
error: function () { alert('error'); }
});
});
});
<script>
In this example, you can see how easily you can return content and scripts of the views without layout for ajax requests.
To do so, follow these steps:
Change the _ViewStart.cshtml
content to:
@{
if(Request.IsAjaxRequest())
{
Layout = "~/Views/Shared/_Partial.cshtml";
}
else
{
Layout = "~/Views/Shared/_Layout.cshtml";
}
}
Add a new layout page named _PartialView.cshtml
having the following content:
@RenderBody()
@RenderSection("scripts", required: false)
Get the view using ajax. For example, assuming you have a Sample
action in Home
controller:
[HttpGet]
public ActionResult Sample()
{
return View();
}
Which returns the following Sample.cshtml
view:
<div id="div1" style="border:1px solid #000000;">
some content
</div>
@section scripts {
<script>
$(function () {
alert('Hi');
});
</script>
}
Get the result using ajax:
<button id="button1">Get Sample Content</button>
<script>
$(function () {
$('#button1').click(function () {
$.ajax({
url: '/home/sample',
type: 'GET',
cache: false,
success: function (data) { alert(data); },
error: function () { alert('error'); }
});
});
});
<script>
Upvotes: 3