How to add a script in a partial view in MVC4? - asp.net

This is the code which I have in my partial view
#model Contoso.MvcApplication.Models.Exercises.AbsoluteArithmetic
#using(Html.BeginForm())
{
<div>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">#Model.Number1</span>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">+</span>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">#Model.Number2</span>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">=</span>
<span>
#Html.EditorFor(model => model.Result)
#Html.ValidationMessageFor(model => model.Result)
</span>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Please note at the bottom of my code, I've got a #section, and I realized that it's not running if I set a breakpoint there. If I move that line in the _Layout.cshtml it works well, but that's not the idea.
How can I tell to MVC4 in a partial razor view that I want to add that library?

You can use
#Scripts.Render("~/Scripts/my-script.js") for .js files and #Styles.Render("~/Content/my-Stylesheet.css") for css files.
Nb: it works for a particular bundle also More details - 'http://www.asp.net/mvc/overview/performance/bundling-and-minification'
it works on any sub-pages in razor including partial views.
for more info google for the usage of these helpers

You can add the script directly at the end of the partial view html, without script section (because script section is not rendered in partial views)
<script language="javascript">
// Your scripts here
// ....
</script>

You can't render layout sections from a partial. Move the section definition to the parent page or layout.

Check out my answer How to render a Section in a Partial View, which allows you to define Scripts and Styles in any view/partial view. It also takes care of duplicate includes.
My personal take is that sections aren't a good solution for styles and javascript includes.

There is no common solution for this issue but you can do the following simplest ways:
1) You can create a set of extension method as the following:
https://stackoverflow.com/a/6671766/5208058
2) Simply move your javascript codes into a separated partial view and on your main view, render 2 partial views. One for the main partial view and the other for your scripts as the following:
{
// markup and razor code for Main View here
#Html.Partial("Main_PartialView")
}
#section Scripts
{
#Html.Partial("JavaScript_PartialView")
}
Hope it helps.

This worked for me allowing me to colocate JavaScript and HTML for partial view in same file for ease of readability
In View which uses Partial View called "_MyPartialView.cshtml"
<div>
#Html.Partial("_MyPartialView",< model for partial view>,
new ViewDataDictionary { { "Region", "HTMLSection" } } })
</div>
#section scripts{
#Html.Partial("_MyPartialView",<model for partial view>,
new ViewDataDictionary { { "Region", "ScriptSection" } })
}
In Partial View file
#model SomeType
#{
var region = ViewData["Region"] as string;
}
#if (region == "HTMLSection")
{
}
#if (region == "ScriptSection")
{
<script type="text/javascript">
</script">
}

This Stackoverflow page provided a full solution to this question: Using sections in Editor/Display templates
TL;DR: Just add the Forloop.HtmlHelpers nuget package https://www.nuget.org/packages/Forloop.HtmlHelpers/ to your project to allow you to run Javascript from Razor Partial Views and Templates in ASP.NET MVC. I have personally used this with my MVC 5 project.

If you want to include specific scripts only in some partial views and avoid spreading them unnecessarily throughout your application, you can do something like this:
Define a bundle pointing to an empty javascript file in your BundleConfig.cs:
bundles.Add(new ScriptBundle("~/bundles/empty").Include(
"~/Scripts/empty.js"
));
In the head section of your _Layout.cshtml, add this variable:
#{
ViewBag.AdditionalBundle = String.IsNullOrEmpty(ViewBag.AdditionalBundle) ? "~/bundles/empty" : ViewBag.AdditionalBundle;
}
In the bottom of your _Layout.cshtml, render any additional bundles you want:
#Scripts.Render("~/bundles/lib")
#Scripts.Render(#ViewBag.AdditionalBundle);
#RenderSection("scripts", required: false)
And finally, in the partial view in which you need any specific scripts, just add the corresponding bundle to the variable:
ViewBag.AdditionalBundle = "~/bundles/mySpecificBundle";
Partial views are rendered before the _Layout.cshtml, so you need that verification at the top of the file. It goes like this: if any partial view assigned a value to ViewBag.AdditionalBundle, then use it. Otherwise, render an empty script.

Noob trick: Define a function in an already loaded file, and call the function on partial view load.
1.Have a separate js file that you load with your usual bundle:
BundleConfig.cs
bundles.Add(new ScriptBundle("~/bundles/CustomScripts").Include(
"~/Scripts/Custom/partial-view.js"
));
Load the custom script bundle like any other bundle in your layout
_Layout.cshtml
#Scripts.Render("~/bundles/CustomScripts");
define a function, in our case OnPartialViewLoad function in the custom js file:
partial-view.js
function OnPartialViewLoad() {
// ... your onLoad work
}
add a document.ready() function to the end of your partial view and call the onLoaded function.
partialView.cshtml
<script type="text/javascript">
$(document).ready(function(){
OnPartialViewLoad();
});
</script>

Related

DotNetNuke MVC including cshtml in div

First MVC attempt in DNN.
I have a fairly involved index.cshtml that I'd like to simplify by using jquery's
$('#mydiv').load() method.
Currently, in the index.cshtml, I'm having to do a bunch of divs like this (very simple) example:
<div id="dvBands">
#using (var ac = new ArtistListingController())
{
ac.Gets();
foreach (var a in ac.Recordset)
{
<div>#a.ArtistName</div><br/>
}
}
</div>
I tried putting the above code in its own _ArtistListing.cshtml and using
$('#dvBands').load("tabId/#Dnn.ModuleContext.TabId/moduleId/#Dnn.ModuleContext.ModuleId/controller/Item/action/_ArtistListing")
with this in my item controller:
public ActionResult _ArtistListing()
{
return View("_ArtistListing");
}
However, not only does it now display the data, it displays the entire page in the div, including the DNN menu and whatnot.
So, how do I separate out my different database calls and include them in the specified div?
In my index.cshtml ---
#{ Html.RenderPartial("_ArtistListing"); }
It looks for a .cshtml file first in the current path and if it can't find it there, in the Shared folders path.
That's it.

How to hide specific element on page from _Layout.cshtml page

I work on mvc 5 project.
On my _Layout.cshtml I have html element named id="topBar" this element displayed in each page.
But I have page named About.cshtml I don't want this page to display only element id="topBar" all other html elements in _Layout.cshtml I want them to be displayed normal in About.cshtml.
Any idea how can achieve described appearance above?
One simple way of achieving this (without javascript), is to set a value in ViewBag inside your about Action and use it in layout like this:
_Layout.cshtml
#if (ViewBag.ShowTopBar ?? false)
{
<div id="topBar">
</div>
}
Action inside your Controller:
public class MyAwesomeController : Controller
{
public ActionResult About()
{
ViewBag.ShowTopBar = true;
return View();
}
}
There are two options:
1. Add an ID to every body element
You could add an ID to the body of each of your pages that contains for example the Controller and Action name and then add a CSS rule to hide the topBar element on the about page.
First, let's create two string variables for the controller and action name. Do this in your _Layout.cshtml:
#{
string controller = ViewContext.RouteData.Values["controller"].ToString();
string action = ViewContext.RouteData.Values["action"].ToString();
}
Next, add the ID to the body:
<body id="#controller-#action">
In your css, you can now add a rule to hide the topbar in the about page (assuming the controller is called HomeController):
#Home-About #topBar {display:none;}
You could also use an extension method to get the controller and action name. For example something like this.
2. Use jQuery on the About page
You could add a Javascript on your about page and use jQuery to hide the topbar (I assume jQuery is already loaded):
<script>
$("#topBar").hide();
</script>
Easier way, just did that: style your page individually:
<style>
#showcase { display: none; }
</style>
Put this on the page that you want to hide, showcase is my section id. ;)

Insert _ViewStart.cshtml

Is that possible to use viewstart only for a particular controller and view?
I was using only _Layou.cshtml file inside views folder.
Now i added _ViewStart.cshtml as common view inside views folder and moved _Layout to Shared folder.
This is program structure:
Homecontroller
public ActionResult Index()
{
return View();
}
Index.cshtml
#{
Layout = "~/Views/_Layout.cshtml";
}
_Layout.cshtml
{
//design code for Index.chtml
}
as per the above code, _Layout rendered for homecontroller .
When done the changes mentioned at the very first line, I'm getting the controls inside _Layout.cshtml in every controller I use.
I use nearly 6 controllers.
How to make this change without disturbing the entire code.
Please help.
PS: I need to introduce _ViewStart into the program since I'm integrating openid with my already developed project.
You can create another _ViewStart.cshtml (in Views/[controller] a sub-folder for example) that will override the root one, something like:
#{ Layout = null; }
You can simply use the ViewBag to determine whether to use Layout or not:
public ActionResult AnotherAction()
{
....
ViewBag.NoLayout = true;
return View();
}
and in your _ViewStart:
#{
if (ViewBag.NoLayout == null || !ViewBag.NoLayout)
Layout = "~/Views/_Layout.cshtml";
}
You can read more about MVC3 Razor layouts on Scott Guthrie's Blog

ASP.NET MVC 3 Partial View in layout page

I'm working on setting up a shared content (navigation) for an asp.net MVC layout page.
Here is my partial view "_LayoutPartial.cshtml" with code to pull navigation data from a model.
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
//Test dump of navigation data
#Html.Encode(item.Name);
#Html.Encode(item.URL);
}
</p>
Here is how the code for my controller "LayoutController.cs" looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyApp.Models.ViewModel;
namespace MyApp.Controllers
{
public class LayoutController : Controller
{
//
// GET: /Layout/
LayoutViewModel layout = new LayoutViewModel();
public ActionResult Index()
{
return View(layout);
}
}
}
Here is the code for the "_Layout.cshtml" page. I'm attempting to call the partial view here using Html.RenderAction(Action,Controller) method.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<p>
#{Html.RenderAction("Index","Layout");}
</p>
#RenderBody()
</body>
</html>
When the layout page executes the #{Html.RenderAction("Index","Layout");} line, it throws out an error message "Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'."
What am I missing friends? How can I call a partial view in a layout page?
Thank you all in advance!
Instead of:
public ActionResult Index()
{
return View(layout);
}
do:
public ActionResult Index()
{
return PartialView(layout);
}
If you don't do that when you return a normal view from your child action, this normal view attempts to include the Layout, which in turn attempts to render the child action, which in turn returns a view, which in turn includes the Layout, which in turn attempts to render the child action, ... and we end up with names like the one ported by this very same site.
Also in your partial you don't need to do double encoding. The # Razor function already does HTML encode:
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
#item.Name
#item.URL
}
</p>
First verify that your child view is inside the Shared directory
#Html.Partial("_LayoutPartial")
OR
#{Html.RenderAction("actionname", "controller name");}
And don't use #Html.Encode(), Razor is already doing for u. Just use
#item.Name
#item.URL
I have solved this error getting on Layout page
System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper
Important !
First create partial view inside shared folder
In Controller ,
public PartialViewResult Userdetails()
{
....
return PartialView("PartialViewName", obj);
}
In Layout Page,
#{Html.RenderAction("action","controller");}
I know this is an old question but I thought I would throw this in here. You can use either Html.Action or Html.RenderAction. They both technically do the same thing but depending on how much content you're returning back can have an impact on which one you should really use for best efficiency.
Both of the methods allow you to call into an action method from a view and output the results of the action in place within the view. The difference between the two is that Html.RenderAction will render the result directly to the Response (which is more efficient if the action returns a large amount of HTML) whereas Html.Action returns a string with the result.
Source

How to handle AJAX driven website in asp.net MVC (lots of views and partialviews)?

I am in the process of putting a new site together which will make use of AJAX to pull through page content should the user have javascript enabled.
So, I am in the situation whereby every Action Method requires a check to see if the request was through AJAX or not, which is straightforward. If the request was through AJAX then I can return a partialview, if not then a full view can be returned.
With this pattern though, I'll need to create a View and a PartialView for every page on the site. The only real difference between them is going to the inclusion of the masterpage.
Am I missing a trick here is is this doubling up of views the only way to go?
Thanks
EDIT - a bit more info
Lets say I had a page that could get accessed through /site/test. Somewhere in my JS I would add a hash to the url like so #/site/test. JS would then watch for any hash changes and load the partial views as needed. If JS was not available though, an entire view would need to be returned.
So for each page I would need the view, which would then include a call to RenderPartial which would load up the partial view which would actually contain the page content. So, for every page there are two files. It just seems there should be a cleaner way of doing this.
Sergio, yes you are missing a trick!!
You should organise your page so that the static content in it is just that - static. This static page then calls the partial(s) that give the dynamic content. this would typically be used in the main page as such (i'm using jquery as per microsofts adopted stance on ajax now):
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>My Header</h2>
<%--lots of stuff omitted--%>
<div id="dynamicList"><%Html.RenderPartial("List"); %></div>
<%--also lots missed out here--%>
<input type="button" id="btnRefresh" value="refresh" />
</asp:Content>
this means that the partial would always be rendered in the initial request. subsequent refreshes would call the partial method in the controller and repopulate the 'dynmaicList' div along the lines of:
<script type="text/javascript">
// you might have a click or similar here to invoke the partial refresh
$(function() {
//click event (or some other 'change' event)
$('#btnRefresh').click(function() {
dynamicList();
});
});
function dynamicList() {
// where action/controller retruns a partialview result
var url = '<%= Url.Action("List", "MyController") %>';
// this is merely a wrapper method around jquery $ajax
SendAjax(url, formParams(), beforedynamicListQuery, dynamicListResponse);
}
function beforedynamicListQuery() {
$("#dynamicList").fadeTo('slow', 0.5);
}
function dynamicListResponse(data) {
if (data.length != 0) {
if (data.indexOf("ERROR:") >= 0) {
$("#dynamicList_errmsg").html(data);
}
else {
var selector = "#dynamicList";
$(selector).fadeTo('slow', 1, function() {
$(this).html(data);
});
}
}
}
</script>
anyway, that's my take on it!! ;)

Resources