How can I arrange to have my favicon cached in MVC3? - asp.net-mvc

I have placed a .ico and a .png file in the folder /Content/Ico and I have the following in my _layout.cshtml
<!-- Favicon -->
<link rel="shortcut icon" type="image/x-icon" href="/Content/Ico/favicon.ico">
<link rel="icon" type="image/png" href="/Content/Ico/tick-circle.png">
a) Is there some way for me to specify how long these favicons are cached for? Should I use some kind of web.config file inside the /Content folder?
b) Some of my code uses the syntax "<link href="#Url.Content("~/Content/ ... Should I be using #Url.Content? What's the difference between using that and just specifying /Content in the href ?

a) You could serve the favicon through a server side controller action in which you specify for how long it should be cached by decorating it with the [OutputCache] attribute:
[OutputCache(Duration = 3600, Location = OutputCacheLocation.Client)]
public ActionResult Favicon()
{
var icon = Server.MapPath("~/content/ico/favicon.ico");
return File(icon, "image/x-icon");
}
and then:
<link rel="shortcut icon" type="image/x-icon" href="#Url.Action("Favicon", "SomeController")" />
b) Always use #Url.Content("~/content/...") and never /content/... to specify relative paths to static files. The reason for that is that the Url.Content helper accounts for the virtual directory name and your site will continue to work even after you deploy it in a virtual directory in IIS. If you hardcode the url like this /content/... it will work locally but once you ship in IIS it will no longer work because now the correct location is /yourappname/content/... which is what the Url.Content helper takes into account.

Related

PNG files not found in ASAR

I have an Electron (1.7.10) application that is reporting it can't find 5 of 7 PNG files in my ASAR. All 7 PNGs are in the same folder, and 2 of them are displayed on screen fine. The other 5 report net::ERR_FILE_NOT_FOUND.
All src attributes for the img tags are dynamically generated and use relative paths (assets/images/MyImage.png). If I extract the ASAR, I can see the files in there, in the correct folder (as referenced by the src attribute).
If I use the console to set the location of my browser to one of the images (document.location.href = "file:///path/to/app.asar/dist/assets/images/MyImage.png") I get the same results - 2 of 7 show OK.
Before packaging my application (with electron-builder), all images show correctly.
Let me guess, you are building a react SPA using react-router, and BrowserRouter?
If so, use HashRouter instead. Electron does not work with SPA's route by default, because a SPA route changes, but the resource path is always relative to index.html.
I haven't evaluated the other answers, but for my particular case, an extremely solution worked. I don't believe this is well documented, so it might be fairly common for people to still encounter this issue. For my particulars, the relevant problem and solution were identified here.
To address, add <base href='./' /> to the index.html (or whatever your starting html file is that hosts your SPA). This is a complete example of mine:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="./" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<meta
http-equiv="Content-Security-Policy"
content="script-src 'Self' 'unsafe-inline';"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
const path = require('path');
path.join(__dirname, 'assets/images/MyImage.png');

Internel URL for .ear file deployment [duplicate]

To working my static file (CSS, JS) I have to write absolute path like /AppName/templates/style/main.css. Is there any solution, that I could write relative path like style/main.css?
If your actual concern is the dynamicness of the webapp context (the "AppName" part), then just retrieve it dynamically by HttpServletRequest#getContextPath().
<head>
<link rel="stylesheet" href="${pageContext.request.contextPath}/templates/style/main.css" />
<script src="${pageContext.request.contextPath}/templates/js/main.js"></script>
<script>var base = "${pageContext.request.contextPath}";</script>
</head>
<body>
link
</body>
If you want to set a base path for all relative links so that you don't need to repeat ${pageContext.request.contextPath} in every relative link, use the <base> tag. Here's an example with help of JSTL functions.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<head>
<c:set var="url">${pageContext.request.requestURL}</c:set>
<base href="${fn:substring(url, 0, fn:length(url) - fn:length(pageContext.request.requestURI))}${pageContext.request.contextPath}/" />
<link rel="stylesheet" href="templates/style/main.css" />
<script src="templates/js/main.js"></script>
<script>var base = document.getElementsByTagName("base")[0].href;</script>
</head>
<body>
link
</body>
This way every relative link (i.e. not starting with / or a scheme) will become relative to the <base>.
This is by the way not specifically related to Tomcat in any way. It's just related to HTTP/HTML basics. You would have the same problem in every other webserver.
See also:
Browser can't access/find relative resources like CSS, images and links when calling a Servlet which forwards to a JSP
Is it recommended to use the <base> html tag?
Just use <c:url>-tag with an application context relative path.
When the value parameter starts with an /, then the tag will treat it as an application relative url, and will add the application-name to the url.
Example:
jsp:
<c:url value="/templates/style/main.css" var="mainCssUrl" />`
<link rel="stylesheet" href="${mainCssUrl}" />
...
<c:url value="/home" var="homeUrl" />`
home link
will become this html, with an domain relative url:
<link rel="stylesheet" href="/AppName/templates/style/main.css" />
...
home link
You start tomcat from some directory - which is the $cwd for tomcat. You can specify any path relative to this $cwd.
suppose you have
home
- tomcat
|_bin
- cssStore
|_file.css
And suppose you start tomcat from ~/tomcat, using the command "bin/startup.sh".
~/tomcat becomes the home directory ($cwd) for tomcat
You can access "../cssStore/file.css" from class files in your servlet now
Hope that helps, - M.S.
Instead using entire link we can make as below (solution concerns jsp files)
With JSTL we can make it like:
To link resource like css, js:
<link rel="stylesheet" href="${pageContext.request.contextPath}/style/sample.css" />
<script src="${pageContext.request.contextPath}/js/sample.js"></script>
To simply make a link:
<a id=".." class=".." href="${pageContext.request.contextPath}/jsp/sample.jsp">....</a>
It's worth to get familiar with tags
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
There is also jsp method to do it like below, but better way like above:
<link rel="stylesheet" href="<%=request.getContextPath()%>/style/sample.css" />
<script type="text/javascript" src="<%=request.getContextPath()%>/js/sample.js"></script>
To simply make a link:
<a id=".." class=".." href="<%=request.getContextPath()%>/jsp/sample.jsp">....</a>
This could be done simpler:
<base href="${pageContext.request.contextPath}/"/>
All URL will be formed without unnecessary domain:port but with application context.
This is a derivative of #Ralph suggestion that I've been using. Add the c:url to the top of your JSP.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:url value="/" var="root" />
Then just reference the root variable in your page:
<link rel="stylesheet" href="${root}templates/style/main.css">

Why use Url.Content for referencing resources?

In almost every ASP.NET MVC example I've come across, I always see Url.Content being used to reference CSS, JavaScript, and Images. Not once has anyone explained WHY to use it.
Anyone care to explain?
What's so bad about doing:
<img src="/Content/Img/MyImage.png" alt="My Image" />
<script src="/Scripts/jquery.js" type="text/javascript"></script>
<link href="/Content/Css/Default.css" rel="stylesheet" type="text/css" media="all" />
What you have works the same as Url.Content(). Url.Content() is just like adding a ~ to be beginning of your paths:
<script src="~/Scripts/jquery.js" type="text/javascript"></script>
Just ensures the path is always correct with routing. You can also make a Html helper method to make this easier:
public static string RenderScript(this HtmlHelper htmlHelper, string file) {
var f = file.EndsWith(".js") ? file : string.Concat(file, ".js");
return string.Format("<script src=\"/public/scripts/{0}\" type=\"text/javascript\"></script>", f);
}
Then you can just put this in your masterpage:
<%=Html.RenderScript("jquery")%>

Asp.net MVC2: CSS/Images paths on internal and local server

I have an Asp.net MVC2 web application. I built the application using VS2008 and tested on internal server, everything was perfect but when I deployed that web application on a local IIS the paths to images in web pages and in CSS file was not correct.
I need to change those paths for working with internal server and local server.
How can I overcome this problem?
Have you tried opening the CSS and Images directly (i.e. not via being called on a page)? Does that work?
How do you link to them on your internal server, if the relative paths don't equate the same, you'll have the problem you describe. An example about how you might fix this is to use Url.Content().
e.g. Instead of using:
<link rel="Stylesheet" href="/Styles/Reset.css" />
You would use:
<link rel="Stylesheet" href="<%=Url.Content("~/Styles/Reset.css")%>" />
This would work out the URL depending upon where the application lives on that box - not relative for the web root.
Edit: In case you need to do this through C# code
// This can be used to create img tag
public static string Image(this HtmlHelper helper)
{
UrlHelper urlHelper = ((Controller)helper.ViewContext.Controller).Url;
TagBuilder imgTag = new TagBuilder("img");
imgTag.MergeAttribute("src", urlHelper.Content("~/Content/images/image.gif"));
imgTag.MergeAttribute("alt", "Alt text");
return imgTag.ToString(TagRenderMode.SelfClosing);
}
To avoid this sort of problems you should always use the built-in helpers to generate URLs. For example:
<script type="text/javascript" src="<%= Url.Content("~/scripts/somescript.js") %>"></script>
and for links
<%= Html.ActionLink("Link text", "action", "controller") %>
Try something like this:
<link href="<%= Url.Content("~/Content/Site.css") %>" rel="stylesheet" type="text/css" />
The tilde ("~") represents the root and the Url.Content does the appropriate magic to get you a nice tidy reference.

Paths in master pages

I've started to work a bit with master pages for an ASP.net mvc site and I've come across a question. When I link in a stylesheet on the master page it seems to update the path to the sheet correctly. That is in the code I have
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
but looking at the source once the page is fed to a browser I get
<link href="Content/Site.css" rel="stylesheet" type="text/css" />
which is perfect. However the same path translation doesn't seem to work for script files.
<script src="../../Content/menu.js" type="text/javascript"></script>
just comes out as the same thing. It still seems to work on a top level page but I suspect that is just the browser/web server correcting my error. Is there a way to get the src path to be globbed too?
<script src="<%= ResolveClientUrl("~/Content/menu.js") %>" type="text/javascript"></script>
Make an extension method. Here's a method:
public static string ResolveUrl(this HtmlHelper helper, string virtualUrl)
{
HttpContextBase ctx = helper.ViewContext.HttpContext;
string result = virtualUrl;
if (virtualUrl.StartsWith("~/"))
{
virtualUrl = virtualUrl.Remove(0, 2);
//get the site root
string siteRoot = ctx.Request.ApplicationPath;
if (!siteRoot.EndsWith("/"))
siteRoot += "/";
result = siteRoot + virtualUrl;
}
return result;
}
You can then write your script ref like:
<script type="text/javascript" src="<%= Html.ResolveUrl("~/Content/menu.js")%>"></script>
Use this instead:
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
or you can use BASE tag in you HEAD section of page. All you links then are relative to location entered in "base" tag, and you don't have to use "../../" and "~" stuff. Except links in CSS files (background url,etc), where links are relative to location of css file.

Resources