ASP.NET MVC including ASP in Javascript - javascript

Is it possible to put ASp.NET tags in my javascript which is in a seperate script file. For example, I have the following
$.getJSON("/Postcode/GetAddressResults/" + $get("SearchPostcode").value, null, function(data) {
which I want to turn into but it does not like the ASP tags!
var action = "<%=Url.Content('~/Postcode/GetAddressResults/')%>" + $get("SearchPostcode").value
$.getJSON(action, null, function(data) {
However this does not seem to work, what am I doing wrong?

Add to your master page(s) a meta tag to hold the value of the current applications path from the host (the bit the ~ represents).
In your Javascript create a function which will resolve a ~ prefixed path using the meta tag content.
Edit
Example as requested:-
Place this code in the head section your master pages:-
<meta id="meta.AppDomainAppVirtualPath"
name="AppDomainAppVirtualPath" value="<%=HttpRuntime.AppDomainAppVirtualPath%>" />
In your javascript include this function:-
function resolveUrl(url)
{
if (url.charAt(0) == "~")
{
if (!resolveUrl.appPath)
{
var meta = document.getElementById('meta.AppDomainAppVirtualPath');
resolveUrl.appPath = meta ? meta .getAttribute("content") : '/';
}
if (resolveUrl.appPath == '/')
return url.slice(1, url.length;
else
return resolveUrl.appPath + url.slice(1, url.length);
}
else
{
return url;
}
}
Now your line of code is:-
$.getJSON(resolveUrl("~/Postcode/GetAddressResults/") + $get("SearchPostcode").value, null, function(data) {

If your JavaScript is in a separate script file, then it won't be processed by ASP.NET, so these tags won't be processed. You'll need them inline in an ASP.NET page for this to work.

No, you can`t.
You can expose a path within your view to javascript, but not directly in your external javascript file.
#David M
Inlining the whole thing is not really neccesary, you can inline the dynamic part and leave the other part hardcoded.
Regards, Peter

Related

Drupal 7 template views preprocess add javascript: what am I doing wrong?

I have read that the best-practice to add a javascript file to a particular view is to use the preprocessor and drupal_add_js. What I'm trying to add is a Facebook app script. I know the script works, because I've tested just adding it in tags right in the header of the view.
What isn't working for me is the code I've added to my theme's template.php file below. As far as I can tell from searching, this should work (obviously replacing THEME_NAME and VIEW_NAME with the actual names), but the js file is just not being added. I also tried just adding it to every page in my theme's .info file, just to see if it would work adding it to every page, but no luck.
function THEME_NAME_preprocess_views_view(&$vars) {
$view = $vars['view'];
if ($view->name == 'VIEW_NAME') {
drupal_add_js(drupal_get_path('theme', 'THEME_NAME') . '/js/facebook.js');
}
}
Just call preprocess for each view. For help visit this link
function bartik_preprocess_views_view(&$vars) {
$function_name = __FUNCTION__ . '__' . $vars['view']->name;
if (function_exists($function_name)) {
$function_name($vars);
}
}
function bartik_preprocess_views_view__test(&$vars) {
$view = $vars['view'];
if ($view->name == 'test') {
drupal_add_js(drupal_get_path('theme', 'bartik') . '/js/facebook.js');
}
}

How to inject code from one text file into an HTML page

I have a series of large html pages in development, each uses a common structure: header / content / sidebar.
Header and sidebar sections have code common to all pages. Only content changes.
During the development phase, I want to be able to make changes to the header and sidebar once and see the results replicated on all pages without having to edit each page separately.
I've done a bit of googling, and the simplest solution seems to be to create 2 separate text files with the code for the header and sidebar sections, and then inject this at the appropriate points in the HTML pages I'm editing.
I know this is not recommended for a live project, as it would dramatically increase the load times, but for dev work it would save me a lot of time.
Would you agree? If so, anybody have any idea what the simplest way to do this is?
Thanks
You would be better to do this with some sort of server-side technology, like PHP. This would make the impact on loading times negligible as the pages would be concatenated before they were sent to the browser.
You would accomplish it by doing something like this:
<?php require('header.php'); ?>
<!-- Main content goes here -->
<?php require('sidebar.php'); ?>
And then have the files header.php and sidebar.php in the same directory as the main files.
Use some sort of serverside templating languate that would allow for you to include files within each other.
If, despite the other answers, you insist on doing this from JavaScript, the following is a module I use :
(function xload (slctr) { //================================================== xload ===
function xloader (src, dst) {
if (arguments.length == 1) {
dst = src;
src = dst.getAttribute ('data-source') || '';
}
var req;
try {
src = src.match (/^([^]*?)(!)?(?:\[\[([^]*?)\]\])?$/);
(req = new XMLHttpRequest ()).open ('GET', src[1], !src[2]);
req.onreadystatechange = function (ev) {
if (this.readyState === 4) {
if (typeof dst == 'function')
dst (req);
else {
dst[dst.tagName == 'TEXTAREA' ? 'value' : 'innerHTML'] = this.responseText;
[].forEach.call (dst.getElementsByTagName ('SCRIPT'), function (s, i) {
var script = document.createElement ('script');
script.innerHTML = s.parentNode.removeChild (s).innerHTML;
document.body.appendChild (script);
})
}
}
};
src[3] && req.overrideMimeType &&
req.overrideMimeType (src[3]);
req.send (null);
} catch (err) { console.log ('xloader error : ', err); }
}
[].forEach.call (document.querySelectorAll (slctr), function (el) { xloader (el); });
}) ('[data-source]'); //------------------------------------------------------ xload ---
Any element, a div for example with a data-source attribute is processed. The data-source specifies the url of the file to be included. When he Ajax request completes, the entire contents of the div are replaced with the text fetched. The data-sourc url may optionally be followed by a ! indicating synchronous load and then by a Mime type enclosed in [[ and ]]
Any scripts in the loaded text are extracted and injected into the document body.
Error conditions are reported on the console.
The module is entirely standalone and processes all elements containing the data-source attribute. It should, of course be loaded after the HTML text of the page.

MVC3 Razor removes script tags from HtmlString

I have a method that adds javascript to the end of partial views if it's an ajax request.
My problem though is that when the script is returned, the script tags have been removed and the function I want to execute is written in plain text.
if (httpContext.Request.IsAjaxRequest())
{
script = "MyNamespace.globals.initFunctions.push(function() { " + script + " });";
return new HtmlString(#"<script type=""text/javascript"">" + script + "</script>");
}
So, instead of getting the desired result of
<script type="text/javascript">MyNamespace.globals.initFunctions.push(function() { MyNamespace.init(); });</script>
I get MyNamespace.globals.initFunctions.push(function() { MyNamespace.init(); }); in plain text.
What could be the reason?
Edit:
Trying it with Html.Raw() did not help. While the script string does contain the script tags, they are still removed when rendered.
#{
string script = ViewUtilities.AddScript("MyNamespace.init();", this.ViewContext.HttpContext);
}
#Html.Raw(script);
Edit 2:
Now I've tried writing it all in the view like this,
<script type="text/javascript">
MyNamespace.globals.initFunctions.push(function() { MyNamespace.init(); });
</script>
and it still removes the tags around the script and renders it as plain text.
I don't know where to go from here...
When I exam the response with Firebug it looks fine but looking at the html it's not.
The HTML is being encoded which happens auto-magically with ASP.NET MVC.
Using #Html.Raw("htmlstring") should give you the raw HTML value of the string without stripping the tags.
You want to use #Html.Raw(whatever function you call)
I think you also probably want to return return MvcHtmlString.Create(fullscript);
If you convert this to an HtmlHelper method, it will work. Change your ViewUtilities class as follows:
public static class ViewUtilities
{
public static MvcHtmlString AddScript(this HtmlHelper htmlHelper, string script)
{
if (htmlHelper.ViewContext.HttpContext.Request.IsAjaxRequest())
return new MvcHtmlString(#"<script type=""text/javascript"">" + script + "</script>");
return new MvcHtmlString("");
}
}
Then, in the web.config file in the Views folder (and in any Views folders in any Areas), add the following to the namespaces list in the <pages pageBaseType="System.Web.Mvc.WebViewPage"> element:
<add namespace="{namespace where ViewUtilities class is located}"/>
Finally, in your view:
#Html.AddScript("MyNamespace.init();")

Creating consistent URLs in jQuery

I am creating a webapp and I have been using tag in my JSPs to ensure that all my links (both to pages and to resources such as images/css) are always consistent from the root of the application, and not relative to my current location.
Some of the content I am creating using jQuery, for example, I am creating a HTML table by parsing a JSON object and using jquery.append() to insert it in to a div.
My question is, if I want to dynamically create a link using jquery how can I achieve a consistent URL regardless of the page being executed? I have tried just building the html with the tag in it, but no joy.
Thanks!
var baseURL = "/* Server-side JSP code that sets the base URL */";
$("<a />", { href: baseURL+"/my/resource/here.jsp" }); //Your proper link
Or you could do:
var baseURL = "http://"+location.host+"/my/base/url/";
//Which gives you something like http://mySite.com/my/base/url/
Get the root value of your webapp into a string using a jsp tag inside your javascript.
var root = < %=myRootVariable%> //This evaluates to http://www.myapp.com
var dynamicBit = "/foo/bar"
var dynamicLinkUrl = root + dynamicBit
var $newa = $("Hello, world");
$someJQElement.append($newa)
Hopefully none of this will occur in the global namespace. Just sayin'

~/ equivalent in javascript

Any smart way of doing a "root" based path referencing in JavaScript, just the way we have ~/ in ASP.NET?
Have your page generate a tag with something like:
<link rel="home" id="ApplicationRoot" href="http://www.example.com/appRoot/" />
Then, have a function in JavaScript that extracts the value such as:
function getHome(){
return document.getElementById("ApplicationRoot").href;
}
Use base tag:
<head>
<base href="http://www.example.com/myapp/" />
</head>
...
from now any link use on this page, no matter in javascript or html, will be relative to the base tag, which is "http://www.example.com/myapp/".
You could also use the asp.net feature VirtualPathUtility:
<script>
var basePath = '<%=VirtualPathUtility.ToAbsolutePath("~/")%>';
</script>
Notice: I don't encode the path to a JSON-string (escape quotes, control characters etc). I don't think this is a big deal (quotes for example aren't allowed unescaped in an URL), but one never knows...
I usually create a variable at the top of the js file and assign it the root path. Then I use that variable when referencing a file.
var rootPath = "/";
image.src = rootPath + "images/something.png";
~/ is the application root and not a literal root, it interpets ~/ to mean <YourAppVirtualDir>/
To do a literal root in JavaScript it's just /, i.e "/root.html". There's no way of getting an application level path like that in JavaScript.
You could hack it in the ASPX file and output it in a tag but I would consider the security implications of that.
Kamarey's answer can be improved to support a dynamic base path:
<head>
<base href="http://<%= Request.Url.Authority + Request.ApplicationPath%>/" />
</head>
This will ensure a correct root path regardless of deployment configuration.
To be fair, this doesn't answer the original question, but it elimiates most needs for getting the root path from javascript. Simply use relative URL's everywhere, without prefixing with slash.
Should you still need to access it from javascript, add an id attribute and use document.getElementFromId() as MiffTheFox suggested - but on the base-tag.
Another option that's a bit simpler and more universal would be to take the following:
<script src="/assets/js/bootstrap.min.js"><script>
and use Page.ResolveClientUrl like so:
<script src='<%=ResolveClientUrl("~/assets/js/bootstrap.min.js")%>'></script>
then regardless of what subdirectory the urls will always be rendered correctly.
The following function will calculate the root of the currently running application. I use it to locate the absolute location of resources, when called from somewhere deep within the application tree.
function AppRoot() {
//
// Returns the root of the currently running ASP application.
// in the form: "http://localhost/TRMS40/"
//
// origin: "http://localhost"
// pathname: "/TRMS40/Test/Test%20EMA.aspx"
//
// usage:
// window.open( AppRoot() + "CertPlan_Editor.aspx?ID=" + ID);
//
var z = window.location.pathname.split('/');
return window.location.origin + "/" + z[1] + "/";
}
In the PreRender of your .NET base page, add this:
protected override void
OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (Page.Header != null)
{
//USED TO RESOLVE URL IN JAVASCRIPT
string baseUrl = String.Format("var baseUrl='{0}';\n",
HttpContext.Current.Request.ApplicationPath);
Page.Header.Controls.Add(new LiteralControl(String.Format(Consts.JS_TAG,
baseUrl)));
}
}
Then in your global JavaScript function, add the following:
function resolveUrl(url) {
if (url.indexOf("~/") == 0) {
url = baseUrl + url.substring(2);
}
return url; }
Now you can use it like this:
document.getElementById('someimage').src = resolveUrl('~/images/protest.jpg');
May be a little much for some projects, but works great for full fledged applications.
Solution for ASP.NET MVC applications
This works when using IIS and also IIS Express in VS.
Put this snippet before all scripts load, in order to have the root url variable "approot".
at your service in the scripts:
<script>
var approot = "#Url.Content("~")";
</script>
--> other scripts go here or somewhere later in the page.
Then use it in your script or page script.
Example:
var sound_root_path = approot + "sound/";
var img_root_path = approot + "img/";
the approot variable will be something either:
"/YourWebsiteName/" <-- IIS
or just:
"/" <-- IIS Express
For ASP.net MVC Razor pages, Create a base tag like below in the <Head> tag
<base href="http://#Request.Url.Authority#Request.ApplicationPath" />
and in all your relative javascript URLs, make sure to start without a slash(/) otherwise it will refer from the root.
For ex. create all your urls like
"riskInfo": { url: "Content/images/RiskInfo.png", id: "RI" },
or
$http.POST("Account/GetModelList", this, request, this.bindModelList);
If you want to use it in HTML Still you can use ~, see this
href = #Url.Content("~/controllername/actionName")
See the check box click event in my MVC Application
#Html.CheckBoxFor(m=>Model.IsChecked,
new {#onclick=#Url.Content("~/controller/action("+ #Model.Id + ", 1)"),
#title="Select To Renew" })

Categories