ASP.NET Webform css link getting mangled - c#

For some reason by css link in a webforms master page is getting mangled by ASP.NET.
The page using the masterpage is located in /subdir1/subdir2/page.aspx
Not sure why it is happening but here is a snippet of the code:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<link href="<%= MyNamespace.Helpers.UrlHelper.CssRoot %>Site.css" rel="stylesheet" type="text/css" />
<script src="<%= MyNamespace.Helpers.UrlHelper.JavascriptRoot %>jquery-1.3.2.min.js" type="text/javascript"></script>
<asp:ContentPlaceHolder ID="cphHead" runat="server">
</asp:ContentPlaceHolder>
</head>
The Html output that is being created is:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
Untitled Page
</title><link href="../../%3C%25=%MyNamespace.Helpers.UrlHelper.CssRoot%20%25%3ESite.css" rel="stylesheet" type="text/css" />
<script src="/Javascript/jquery-1.3.2.min.js" type="text/javascript"></script>
</head>
Why is this working for the script tag but mangling the link tag and not actually executing the code included. If I change the 'link' tag to be a 'script' tag (which is wrong but for testing purposes) it produces the proper html I would expect. Why is ASP.NET messing with my link tag for my Css but not the script tag for the javascript?
Is there something special about the link tag to make ASP.NET think it needs to mangle it?

This is a separate answer based on approach and might be more what you are looking for. The reason I found for the string mangling is the HtmlLink object has internal handling of the href value during rendering. Using .NET Reflector I found an Overrides RenderAttributes method. This is the code for it:
Protected Overrides Sub RenderAttributes(ByVal writer as HtmlTextWriter)
If Not String.IsNullOrEmpty(Me.Href) Then
MyBase.Attributes.Item("href") = MyBase.ResolveClientUrl(Me.Href)
End If
MyBase.RenderAttributes(writer)
End Sub
What I believe is happening is the RenderAttributes method is being called before your helper line is being parsed and is using ResolveClientUrl against the string "<%= MyNamespace.Helpers.UrlHelper.CssRoot %>Site.css". The solution of using "~/" URL strings isn't affected by this because ResolveClientUrl is able to understand that notation.
I see two solutions for you at this point. 1) Use the Edit #2 approach of injecting the helper's URL string into the element during Page_Load or Page_PreRender, or 2) Create your own Overrriden version of the HtmlLink element that doesn't try to use ResolveClientUrl. #1 would definitely be the easier solution.
Hope this helps shed some light on the issue.

Perhaps a solution would be to specify your <link> and <script> tags from your master page's codebehind.
private void ConstructLinkAndScriptTags()
{
string cssTag = "<link href='" + MyNamespace.Helpers.UrlHelper.CssRoot + "Site.css' rel='stylesheet' type='text/css' runat='server' />";
cph.Controls.Add(new LiteralControl(cssTag));
}

You could try changing
<link href="<%= MyNamespace.Helpers.UrlHelper.CssRoot %>Site.css" rel="stylesheet" type="text/css" />
to
<link href='<%= MyNamespace.Helpers.UrlHelper.CssRoot %>Site.css' rel="stylesheet" type="text/css" />
Note the single quotes on the second instance

Try runat="server" tags in the elements
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<link runat="server" href="<%= MyNamespace.Helpers.UrlHelper.CssRoot %>Site.css" rel="stylesheet" type="text/css" />
<script runat="server" src="<%= MyNamespace.Helpers.UrlHelper.JavascriptRoot %>jquery-1.3.2.min.js" type="text/javascript"></script>
<asp:ContentPlaceHolder ID="cphHead" runat="server">
</asp:ContentPlaceHolder>
</head>
Edit: Do you have to use the helper object? Is it doing more than just making your links dynamic? When runat="server" is set, you can sometimes use dynamic URLs using the ~ character. You could try this instead:
<head runat="server">
<link id="SiteCssLink" runat="server" href="~/Css/Site.css" rel="Stylesheet" type="text/css" media="all" />
</head>
Edit #2: Try injecting the URL into the link element from the Page_Load or Page_PreRender events in the code behind of the page. You will need the element to have runat="server" for this to work.
Protected Sub Page_PreRender(ByVal sender as Object, ByVal e as System.EventArgs) Handles Me.PreRender
SiteCssLink.Href = Page.ResolveClientUrl(String.Concat(MyNamespace.Helpers.UrlHelper.CssRoot, "Site.css"))
End Sub

It was not wise for ASP.NET team to make link tags auto-adjust their href attributes, but the best way I've found to deal with it is to:
Dynamically insert the link tag into a Literal control.
Remove the runat="server" from the head tag.

It may be a bit hacky, but gets the problem solved, and looks "somewhat" like regular html.
<link <% this.Response.Write( "href=\"" + Links.Content.Site_css + "\""); %> rel="stylesheet" type="text/css" />
Note that in this example I am u sing T4MVC. As posted by Chris Porter, the problem is href. By calling the Response.Write you get around that. Enjoy!

Related

script never run in .cshtml file of mvc

This is the formal structure of my .cshtml file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dashboard</title>
<link rel="stylesheet" href="~/lib/Hover/hover.css" />
<link rel="stylesheet" href="~/lib/fontawesome/css/font-awesome.css" />
<link rel="stylesheet" href="~/lib/weather-icons/css/weather-icons.css" />
<link rel="stylesheet" href="~/lib/ionicons/css/ionicons.css" />
<link rel="stylesheet" href="~/lib/jquery-toggles/toggles-full.css" />
<link rel="stylesheet" href="~/lib/morrisjs/morris.css" />
<link rel="stylesheet" href="~/lib/select2/select2.css" />
<link rel="stylesheet" href="~/lib/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" />
<link rel="stylesheet" href="~/css/quirk.css" />
<script src="~/lib/modernizr/modernizr.js"></script>
<script>
alert("hello from top");
</script>
</head>
<body style="background:none;">
---Several divs------
<script src="~/lib/jquery/jquery.js"></script>
<script src="~/lib/jquery-ui/jquery-ui.js"></script>
<script src="~/lib/bootstrap/js/bootstrap.js"></script>
<script src="~/lib/jquery-toggles/toggles.js"></script>
<script src="~/lib/morrisjs/morris.js"></script>
<script src="~/lib/datatables/jquery.dataTables.js"></script>
<script src="~/lib/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.js"></script>
<script src="~/lib/select2/select2.js"></script>
<script src="~/js/quirk.js"></script>
<script>
alert("hello from bottom");
</script>
</body>
</html>
Actually It's the design provided by our designer, The first alert message from head is popping up successfully so that it's sure javascript is not disabled in my browser, But the last alert is never shown. When I link the external scripts then that also never works either. This is really annoying. I referenced this question and many more in stackoverflow, But nothing solved.
How can I find out what actually happened here ? Is it because some error in previous js files ? OR it's because of old html4 ? There is nothing in my Action method except return View(); statement so that I think it's not necessary to post.
One additional thing is I've rendered one partial view using #Html.Action("...") in body, I think it's not the issue because I tried removing it as well. Please guide me, I am a beginner.
It's seems the same mistake I did some months ago. Your page is started from
<!DOCTYPE ...>
<html ...>
means It clarifies that you are not using any master layout page so any kind of #Scripts.Render as given in the answer you referenced won't work in the current situation. Just a simple solution is set Layout to null at the top of the page like,
#{
Layout = null;
...
}
and everything will work fine.

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)

I am stuck with this error and found a work around and the solutions works for me, but i i would like to know is it the best way to fix the issue and i want to make sure that it wont affect any other pages badly. Hope the experts will help.
If this was the best solution then many of you can save your heads.
This error occurs when a code block is placed in the MasterPage. Place the code block in a placeholder to resolve the issue.When adding AJAX extenders to your Web page, it will attempt to register scripts in the head. If code blocks are present in the MasterPage, an error might occur.
To resolve this issue, simply move the code block into a placeholder in the head of your MasterPage, like so:
<head id="Head1" runat="server">
<title>Untitled Page</title>
<link href="StyleSheet.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="myPlaceholder" runat="server">
<script language="javascript" type="text/javascript" src="<%= Page.ResolveClientURL("~/javascript/global.js")%>"></script>
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
</head>
The error is logical you can not confuse the rendered controls after they rendered by using the <%= %>
One way to solve this issue is to use a literal control, and render the script line on code behind.
<asp:ContentPlaceHolder ID="myPlaceholder" runat="server">
<asp:Literal runat="server" ID="txtIncludeScript" EnableViewState="false"></asp:Literal>
</asp:ContentPlaceHolder>
and on code behind. Check for null because if you change the placeholder the literal is null. Also set EnableViewState=false because you set it on every Page_Load and you do not wish to save it to viewstate.
if(txtIncludeScript != null)
{
txtIncludeScript.Text =
string.Format("<script language=\"javascript\" type=\"text/javascript\" src=\"{0}\"></script>",
Page.ResolveClientUrl("~/javascript/global.js"));
}
ContentPlaceHolder requires a master page, so you can replace that tag with some other element that can be ran at the server in case your page does not have a master page and you cannot get rid of the
<head id="Head1" runat="server">
<title>Untitled Page</title>
<link href="StyleSheet.css" rel="stylesheet" type="text/css" />
<div runat="server">
<script language="javascript" type="text/javascript" src="<%= Page.ResolveClientURL("~/javascript/global.js")%>"></script>
</div>
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
</head>

How to avoid multiple $(document).ready()

I work on a ASP.NET application using Jquery. Jquery is really powerfull and I use a lot of it.
In my master page I include all libraries I use and a js file who contain the jquery code available for all the application (interface interactions). In this js File (Main.js) I make some things so I use the $(document).ready( ... etc .. )
But in some pages, who are more complex I need to use some other jquery code.. So I add some head Content with other script tag.. And this the problem, I have to add the $(document).ready() instruction again.
There is a lot of problems with my asp controls with this way to do, the autopostback controls doesn't do their autopostback.. I think this is a problem with the multiple $(document).ready() declaration because when I remove the second one(in the page not in the master page) the controls are working.
So how can I do to add some javascript code in a specific page without multiple $(document).ready() declaration. (I don't want to embed all the jquery code in all pages).
I hope I'm clear enough, thanks for responses
Edit here is code
Master page part
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
<link href="Styles/jquery-ui-1.8.9.custom.css" rel="stylesheet" type="text/css" />
<link href="Styles/menu.css" rel="stylesheet" type="text/css" />
<script src="/js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script src="/js/jquery-ui-1.8.7.custom.min.js" type="text/javascript"></script>
<script src="/js/jquery.cookie.js" type="text/javascript"></script>
<script src="/js/jquery.ui.datepicker-fr.js" type="text/javascript"></script>
<script src="/js/jquery.color.js" type="text/javascript"></script>
<script src="/js/Menu.js" type="text/javascript"></script>
<script src="/js/iphone-style-checkboxes.js" type="text/javascript"></script>
<script src="/js/jquery.tools.min.js" type="text/javascript"></script>
<script src="/js/Main.js" type="text/javascript"></script>
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
Some content....
</body>
</html>
Main.js
$(document).ready(function () {
/// <reference path="jquery-1.4.4-vsdoc.js" />
//There is a lot of content here......
});
And A page
<%# Page MasterPageFile="~/Site.master" Language="C#" AutoEventWireup="true" CodeBehind="Dep.aspx.cs" Inherits="Dep" %>
<asp:Content ID="HeadContent1" ContentPlaceHolderID="HeadContent" runat="server">
<link href="../../Styles/nyroModal.css" rel="stylesheet" type="text/css" />
<script src="../../js/jquery.nyroModal.custom.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#tbxDateDebut').datepicker();
$('#tbxDateFin').datepicker();
$('.nyroModal').nyroModal();
});
</script>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
//Here comes the controls... (lot of code)
</asp:Content>
main.js
$(document).ready(function () {
//There is a lot of content here......
if ($.pageReady) $.pageReady($);
});
page.js
<script type="text/javascript">
$.pageReady = function() {
// fired on DOM ready
}
</script>
The answer is in your question:
But in some pages, who are more complex I need to use some other jquery code.. So I add some head Content with other script tag.. And this the problem, I have to add the $(document).ready() instruction again.
"But in some pages..."
Unfortunately you have to add a reference for every js file that refers to uncommon elements. That is if you have page 1 with a <div id="element1"> and another page (page 2) with <div id="element676"> you would not want to include all in the Jquery handling into Main.js . In fact that would give an error if you had not yet seen page 2.
Damn you guys are quick.... as I was writing #Raynos gave the correct answer.
well an alternative is to move all of you jquery document ready to the bottom of your page
<body>
... here goes your other html ....
<script>
//$(document).ready(function(){//this is not needed
... here goes the first ready...
//});//this is not needed
//$(document).ready(function(){//this is not needed
... here goes the second ready ... and so on...
//});//this is not needed
</script>
</body>
So in effect you are using document.ready when all other elements are ready :) PS
I'm inclined to think that there's something at work here other than your multiple $(document).ready() calls. AFAIK, multiple calls against $(document).ready() (and even bubbled-up versions, like $('#someid').ready()) shouldn't cause issues as they are all aggregated together silently by jQuery for you.
I'd double-check my syntax for starters, and make sure that all your blocks are properly encapsulated, all statements end with a ;, and all that jazz.

Problem with loading CSS while invoking page by Server.Transfer()

While I'm using Response.Redirect("~/Pages/Page.aspx"), style is loaded on the page, but unfortunately it is not loaded while I'm using Server.Transfer("~/Pages/Page.aspx") method.
The page looks following:
<html>
<head runat="server">
<link href="../Css/Layout/style.css" type="text/css" rel="stylesheet" />
</head>
<body></body>
</html>
How to make the page load style.css using Server.Transfer() ?
Regards
The problem is that you use a relative path to your CSS file, you should use an abolute path.
If the css folder is inside your application root, you can use
<html>
<head runat="server">
<link href="/Css/Layout/style.css" type="text/css" rel="stylesheet" />
</head>
<body></body>
</html>
or even
<html>
<head runat="server">
<link href="~/Css/Layout/style.css" type="text/css" rel="stylesheet" runat="server" ID="aUniqueId" />
</head>
<body></body>
</html>

Appending to default title in asp.net masterpage

I am using the MVC to add a title to the masterpage with a content place holder. The default MVC masterpage template uses the following code:
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server"/></title>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>
When I try to add defaulted text to the front of the content holder, it doesn't show the text in the final rendered page. I am trying to get the page to show a default title with appended contentplaceholder text.
Example:
(Default Text) (ContentPlaceHolder Text)
My Page - About Us
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>My Page - <asp:ContentPlaceHolder ID="TitleContent" runat="server"/></title>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>
I am looking for a way to accomplish this without having to use code behind. Any ideas?
It seems we should use
<asp:Literal runat="server" Text=" - MySite" />
instead of
<asp:LiteralControl runat="server" Text=" - MySite" />
mentioned in the article, because otherwise we get "Unknown server tag" error.
After looking further, Phil Haack actually posted an article which was a solution to my question. It can be found at Haacked.
In summary he said that everything that is rendered in the head is rendered as a control, and the fix for my question above is to put an asp literal control in the title to have it correctly generate the text.
<%# Master ... %>
<html>
<head runat="server">
<title>
<asp:ContentPlaceHolder ID="titleContent" runat="server" />
<asp:LiteralControl runat="server" Text=" - MySite" />
</title>
</head>
...
Why?
<title>
<asp:ContentPlaceHolder ID="titleContent" runat="server" />
<%= "- My Site" %>
</title>
Works just as well. Without the hassle?
I prefer to use this:
<title>Site Name - <%=Page.Title%></title>
Much cleaner than using a literal control..
If you are using MVC and are passing the title in some object from the controller to the page I would use inline code to display this.
We use the MVC contrib functions to get typed data directly from the view data in the master page thus:
<head>
<title>My Page - <%= ViewData.Get<Model.Page>().Title %></title>
</head>
As a point of note we have removed all code behind files from every view we have to make the views more legible, we find this much better than having code behind for each view.

Categories

Resources