Strange inline code error from ASP.NET - asp.net

This is a really strange one. I am trying to add a cache value to my css stylesheet references in order to invalidate the http header caching I have set. I have the following code:
<link href="/css/Continuity2/layout.css?cache=<%=Global.CACHE_KEY %>" rel="stylesheet" type="text/css" />
The above is rendered as follows and does not seem to be picking up the inline code:
<link href="/css/Continuity2/layout.css?cache=<%=Global.CACHE_KEY %>" rel="stylesheet" type="text/css" />
The even stranger thing is, I have the following code for my javascript references:
<script type="text/javascript" src="/js/ajaxhelper.js?cache=<%=Global.CACHE_KEY %>"></script>
And this references as expected:
<script type="text/javascript" src="/js/ajaxhelper.js?cache=70BE31E0-E694-45ff-A920-D6564DA2FB79"></script>
Has anyone any idea why on earth this would happen?

<link> tags inside a <head> tag are converted into HtmlLink objects.
You can resolve the issue either by setting the property value programmatically from your code behind, or by using a control adapter.
It would probably also work if you moved the tag outside of your head section, although that can have an effect on the way your page is rendered (potential flashes, etc after the CSS is loaded).
I should also add that using a query string on static files to force versioning is usually not an ideal solution, because it prevents the high performance kernel mode HTTP driver (http.sys) from caching the file.

Related

Why does MVC automatically expand virtual URLs?

In my Layout.cshtml file I have the following line:
<link rel="stylesheet" href="~/Content/bootstrap.css" />
My assumption was that since I did not include Url.Content() call, it would actually just render what I wrote but not expand the virtual URL automatically. This assumption is wrong - the generated HTML does include the correct path to the file, not the virtual path I entered.
If I wrap the <link> in <script>
<script type="text/html">
<link rel="stylesheet" href="~/Content/bootstrap.css" />
</script>
then the URL is not expanded.
Which part of ASP.NET MVC does this automatic parsing of HTML and is there a way to control it?
This was a new feature included in Razor2 and ASP.NET MVC 4 and was designed to make life easier by not having to use Url.Content everywhere.
http://www.davidhayden.me/blog/asp.net-mvc-4-the-new-tilde-slash-feature-in-razor-2
The feature only works inside standard HTML attributes and that's why you don't get it inside your <script> tag or anywhere else.
You could use a simple output write to work around this:
<link rel="stylesheet" href="#("~/Content/bootstrap.css")" />

Asp.net link runat server w3c validator

when i run a link server side like this:
<link runat="server" id="staticCss"
href="....css?v=0" media="all" rel="stylesheet" type="text/css" />
asp.net renders it with
<link runat="server" id="staticCss"
href="....css?v=0" media="all" rel="stylesheet" type="text/css" ><link>
and this fails the w3 validation
Stray end tag link.
becasuse link tag can't end with link but must end with /
How can i avoid it?
As far as I know, it can’t be avoided. These are the alternatives that you have:
Use a static link tag without the server processing, if you can
Ignore the validation error: browsers handle this markup well and you shouldn’t have any issues on your website
Use a .net literal to spit out the markup as text: this way you are in total control of the formatting
I have been struggling with .net generated html for a long time, it can be very frustrating. If anyone knows of other ways to solve this I would be very interested to learn.

Implementing CSS as a variable in the site.master page in ASP.NET MVC3

I am implementing a web application using ASP.NET MVC3. In the application I want to add the option of switching between CSS files (for themes) based on clicking some links. I did some research and I came up with the following:
To pass data to site.master, the good solution is to create an abstract controller and inherit that into the other controllers that have site.master as their template, according to this article: Passing Data to View Master Pages
I can pass a viewbag message to the link which controls the css file URL to set the current css file to use, based on the code that I am seeing being passed to scripts at the top of the site.master page:
script src="<%: Url.Content("~/Scripts/jquery-1.5.1.min.js") %>" type="text/javascript"
So I created an abstract controller, ApplicationController, with the following method:
public ApplicationController()
{ViewBag.NewMessage = "../../Content/Site2.css";}
And in the site.master, I included this link:
<link href="<%: (string) ViewBag.NewMessage %>" rel="stylesheet" type="text/css" />
However, that doesn't seem to be working, as it is being interpreted as:
<link href="<%: (string) ViewBag.NewMessage %>" rel="stylesheet" type="text/css" />
And only when I remove the quotation marks:
<link href=<%: (string) ViewBag.NewMessage %> rel="stylesheet" type="text/css" />
is it being interpreted correctly (and the webpage gets rendered with the correct css), except that it violates html standards:
<link href=../../Content/Site2.css rel="stylesheet" type="text/css" />
Any suggestion about how to go tackling this problem or is there a more elegant solution I'm missing? I was going to proceed and implement variables in the ApplicationController that get selected based on links the user clicks at the top of the page, to switch between css styles.
Thank you!
Check to make sure your <head> tag does not have runat="server".
After making this change, be sure to check your script and css tags. This change can break the paths if you use the ~/ to ref app root. To help with this, use the Url.Content(...) helper.

How do I validate noscript+meta refresh tag in xHTML?

For visitors that don't support JavaScript, I'm redirecting them to a certain page - "js.html".
For this, I have the following in all my files:
<noscript>
<meta http-equiv="Refresh" content="0;URL=js.html" />
</noscript>
Of course, this doesn't validate in XHTML as noscript must be placed in <body>.
But when I place that code in the body of my document, I get another error, because meta tags can only be used in the <head> section, so I'm kind of stuck in an infinite loop here.
Is there a way to make this validate? It works fine in all browsers so it's not a big deal, I just would like to validate my app.
Here is what you could do:
Insert the meta into your head but with a refresh of let's say 2 seconds. And very next to that place a SCRIPT tag that removes that meta refresh. So any JS user will not be redirected:
<meta id="refresh" http-equiv="Refresh" content="10;URL=js.html" />
<script type="text/javascript">
$('refresh').remove();
</script>
The browser might hav already "mentioned" the meta refresh. So you could just use JavaScript to write an opening and closing HTML comment (inlcude an opening script tag to close the script tag of the second document.write) around it:
<script type="text/javascript">
document.write("<!-- ");
</script>
<meta http-equiv="Refresh" content="2;URL=js.html" />
<script type="text/javascript">
document.write(' --><script type="text/javascript">');
</script>
I could successfully tested this one.
Just a hint on how I handle non-js users. I have a css class called "js" which I add to any element that should only be visible for javascript users. Through javascript I add a css file containing a rule for the class "js" that shows every element with the "js" class. All links (functions) are alo designed, that they can be used without javascript or in a new tab clicking a link while holding down CTRL.
I've tried all the suggestions I could find for this, including the answers to this question, but none worked. Kau-Boy's answer to this question didn't work for me (as it comments out both the meta tag and most of the second code script block, then js breaks on '); which it tries to interpret after the comment is closed i.e. this happens:
<script type="text/javascript">
document.write("<!-- ");
</script>
<!-- <meta http-equiv="Refresh" content="2;URL=js.html" /><script type="text/javascript"> document.write(' -->
<script type="text/javascript">
');
</script>
I took inspiration though from what it did do, and put together the following which seems to work:
<script type="text/javascript">
document.write('\x3Cscript type="text/javascript">/*');
</script>
<meta http-equiv="Refresh" content="0;URL=js.html" />
<script type="text/javascript">/**/</script>
Essentially, if javascript is enabled, we get 3 script elements, one of which is the meta tag tricked inside a javascript comment, so it doesn't redirect. If javascript is disabled, all it sees is two script elements which it ignores, and the unmolested meta element, so it redirects.
Note: if you serve up your page with application/xhtml+xml content type (which you probably should be doing, I suppose, if the document is xhtml), this will break js in the browser, since the write method will usually be disabled.
As you've discovered, this problem cannot be resolved in HTML4. In HTML5 currently, however, noscript is valid in head, so you could use HTML5 for validation purposes. (The HTML5 validator is much better than the HTML4 one anyway).
One caveat though: HTML5 has an outstanding issue (ISSUE-117) which calls for deprecation of noscript, so it's possible that by the time HTML5 reaches last call, noscript will no longer be valid in HTML5.

ASP.Net Master Page and File path issues

I'm trying to add a script reference to jQuery in my master page so that it will work for any page. It currently looks like this
<script type="text/javascript" src="jquery.js"></script>
The problem is that the path is always relative to the executing aspx page so this will only work if the "jquery.js" file is located in the same folder. To make it work I have to change the line to:
<script type="text/javascript" src="../../jquery.js"></script>
This is obviously less than ideal because it will only work for pages that are two levels deep from the root folder. If I try the following, IIS throws an error about an unexpected character.
<script runat="server" type="text/javascript" src="~/jquery.js"></script>
Any ideas?
EDIT: I forgot to mention as well that the script MUST be in the head tag
The current top answer throws a "ASP.NET Ajax client-side framework failed to load." error when I add it to my master page. Its thrown from javascript and not the .Net compiler. If I move the ScriptManager to the head section where it should be I get a compile error about the ScriptManager needing to be inside a form tag.
The third answer throws a "Illegal characters in path." exception from the compiler
EDIT 2: When I add that line to my head tag I get this error from IIS.
The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)
SOLVED: I took the edited response from the answer below and put it inside an asp:ContentPlaceHolder element
You could use a ScriptManager:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="~/jquery.js" />
</Scripts>
</asp:ScriptManager>
EDIT: If you absolutely need this in your <head> section, you could do something like:
<head>
<script type="text/javascript"
src="<%= Page.ResolveClientUrl("~/jquery.js") %>"></script>
</head>
EDIT 2: According to the comments, if you are observing that
The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)
you may need to change the above to use the data-binding syntax:
<head>
<script type="text/javascript"
src="<%# Page.ResolveClientUrl("~/jquery.js") %>"></script>
</head>
Try <%# instead of <%= in Master page under head section
<script type="text/javascript"
src="<%# ResolveUrl("~/YourScriptFolder/YourJQueryOrJavascript.js") %>">
</script>
Then in Code Behind of Master page under Page_Load Event
Page.Header.DataBind();
Now you are good to go with either jQuery and JavaScript as well as CSS just you need to change your path in ResolveUrl which file you want to handle CSS, JavaScript, jQuery.
If you're not going to us asp:ScriptManager or absolute paths then you can do it like this:
<script runat="server" type="text/javascript"
src='<%= Page.ResolveUrl("~/jquery.js") %>'></script>
I do not know whether you guys found the solution to your problem or not. I was facing the same problem and going nuts to figure out why do I get "jQuery is undefined" error on the plugins i use. I tried all the solutions i get from the internet but no luck at all.
But, suddenly something splash on my mind that may be the script files should be in order. So, I moved the jquery referece to first position and everything start working like charm.
Remember guys, if you're using any plugins with jquery, make sure you use the folloing order of setting reference to those fiels.
reference to the jquery library
reference to the other subsequent plug-in libraries and so on...
e.g.:
"script src="js/jquery-1.3.2.min.js" type="text/javascript"...
"script src="js/jqDnR.min.js" type="text/javascript"...
"script src="js/jquery.jqpopup.min.js" type="text/javascript"...
"script src="js/jquery.bgiframe.min.js" type="text/javascript"...
Always make sure you must put the jquery reference to first and then the subsequent libraries.
Hope, this solves your problem especially when you use with MasterPages. Its very strange that it works no matter what order you use when you don't use MasterPages but when you do, then it somehow requres the proper order.
Good luck and happy coding,
Vincent D'Souza
Look at How to Run a Root “/”. This should fix all your issues regarding unresolved .js file paths. You basically reconfigure the VS Dev server to run your application as localhost:port/ as opposed to the regular localhost:port/application name/ making name resolution work the same way as it does on IIS.
For absolute path of the file for any page use it following:
<script type="text/javascript" src="<%= Page.ResolveClientUrl("~/jquery.js") %>"></script>
<script type="text/javascript" src="/full/path/to/jquery.js"></script>
If this script tag goes directly to the browser, then you unlikely can substitute your site's root there. At least not on the server. So you can:
Deploy site to the root of domain
name and use absolute paths
(simplest solution).
Insert this
link with server control.
Preprocess resulting HTML before
sending it to the client (with
HttpResponse.Filter).
You can also use <base> HTML tag:
<base href="http://www.domain.com"></base>
and then all the links in header section are relative to base address:
<script type="text/javascript" src="scripts/jquery.js"></script>
It's often useful when you have multiple publishing destinations, like local dev web server, demo server, etc. You just replace that base URL.
<body>
<script language="javascript" src='<%= this.ResolveClientUrl("~/full/path/to/jquery.js") %>' type="text/javascript"></script>
</body>

Resources