Images not displaying from theme layout (Orchard CMS) - asp.net

I'm trying to create theme for Orchard CMS. The template I have wasn't made for it so I have some troubles displaying images from Layout.cshtml.
This is the current folder structure on my web server (theme folder structure only):
Theme/Content/Images/Image.jpg
Theme/Views/Layout.cshtml
Theme/Styles/Site.css
The following line doesn't display image (located in Layout.cshtml):
<img src="../Content/Images/bgBig.jpg" alt="Big background image" />
However, this line does display the image (located in Site.css):
background-image:url('../Content/Images/bgLines.png');
I believe the problem is that Layout.cshtml doesn't display the image from Theme/Views/Layout.cshtml, but from the other location. If someone knows what would be that location or how to override it I would be thankful.

I might be a little late, but this may be of help to others.
To get the current theme and then build an dynamic path (as opposed to an absolute path) use this:
WorkContext.CurrentTheme: Gets the current working theme ExtensionDescriptor.
Then give it to the Html.ThemePath URL builder:
Ex.
Html.ThemePath(WorkContext.CurrentTheme, "/Content/Images/SomeImage.png")
Have fun!
Best regards,
Tiago.

When adding images in Layout.cshtml you should use the full path to your theme (eg. /Themes/My.Theme/Content/Images/MyImage.jpg). Remember that the paths you provide in [img] tag are relative to the URL in browser, not the path on the server. In MVC those are almost never equal.
Layout.cshtml view file gets loaded as a part of every single request, so relative paths placed inside will almost always break.
Imagine you have two Orchard pages: site.com/mypage and site.com/something/mypage. Layout.cshtml gets rendered in both of them. Relative URLs working for the first will surely break when you access second one.
CSS stylesheets are loaded directly by specifying absolute path to the physical files in /Themes/YourTheme/Styles folder (default), so in this case relative URLs will work.
HTH

Thx Tiago for your solution. I think this is in fact the correct solution, as opposed to linking the full path which I think would require the Orchard site to be on the root of the domain.
The full image reference of the original question would look like this:
<img src="#Url.Content(Html.ThemePath(WorkContext.CurrentTheme, "/Content/Images/bgBig.jpg"))" alt="Big background image" />

I'm surprised that nobody's mentioned that you need the following web.config in the folder in which your images/scripts/styles reside (see the orchard docs)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location,
return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!-- iis7 - for any request to a file exists on disk,
return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page. -->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule"
preCondition="integratedMode" resourceType="File"
requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>
Additionally, as others have pointed out, this is the most reliable way of locating an image:
<img src="#Url.Content(Html.ThemePath(WorkContext.CurrentTheme, "/Content/Header.png"))" />

if you examine the source, it should show you where it's trying to find that image and failing. It's most likely the relative path it's having issue with, try an absolute path in the css to see if that's the issue. without the actual site, I can't know for sure.

Related

Css in different folder

I am trying to make something like "templates system" it might allow user to change site template. In admin panel for example.
My current files structure
-Controllers
-Models
-Views
--Templates
---DefaultTemplate
----css
-----style.css
----Index.cshtml
In default controller (home) i check current template name and show right view
private ViewResult TemplateView(string viewName)
{
return View($"~/Views/Templates/{GlobalSettings.CurrentTemplate}/{viewName}.cshtml");
}
And some template View (Index.cshtml)
.....
<link rel="stylesheet" href="~/Views/Templates/DefaultTemplate/css/style.css" type="text/css" />
.....
But I dont know how write correct path to my css\js\ images in right template forder.
I have tried
./css/style.css
#Url.Content("/css/style.css")
But in result HTML it is like mysite.com/css/style.css so i got 404 (not found)
I have also tried this
~/Views/Templates/DefaultTemplate/css/style.css
In this case i got 404 too.
So, can anybody help me? How to write correct URL to CSS, images, hs etc ?
The web.config file in the /Views folder restricts all access to files in the folder by default:
Add code to your web.config file:
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
Note: It's not good practice to store css files inside view folder.

Running Autoprefixer with BundleTransformer / LESS in Debug mode

So I currently use BundleTransformer, LESS and I'm trying to add the Autoprefixer post processor. This plugin automatically takes css like transform: scale(1.5) and converts it to -webkit-transform and -moz-transform.
If I am in release mode or have BundleTable.EnableOptimizations=true then everything works just fine and the prefixes are added as expected.
In debug mode however, all the individual CSS / LESS files in my bundle are present in the HTML as separate requests. I'm using this command in my CSHTML file:
#Styles.Render("~/Content/css/lessbundle")
i.e. In debug mode this gets expanded out to LINK tags for :
/cs/something.css
/css/lessfile1.less
/css/lessfile1.less
instead of a single file
/Content/css/lessbundle?v=RFAUSIwb-jEuuo4vHNTnTkE2LrN2jfHglX-Hk8HIF481
For the LESS files IIS automatically converts them, however it does not apply the Autoprefixer.
Is there a way to get Autoprefixer to work when requesting raw .css and .less files?
If not it seems kind of pointless to me because the only alternative I see is to request directly the 'Content/css/lessbundle virtual URL - which will get run through the Autoprefixer. It will only get minified for a release build.
In the documentation (sections: “Examples of usage”, “Debugging HTTP-handlers” and “Postprocessors”) describes how to solve this problem. I will list the basic steps:
For debugging HTTP-handlers to use a configuration settings from bundles need to add in the RegisterBundles method of App_Start/BundleConfig.cs file the following code:
BundleResolver.Current = new CustomBundleResolver();
In order to these settings can be applied to CSS- and JS-assets need to register the debugging HTTP-handlers CssAssetHandler and JsAssetHandler in Web.config file. To do this in the IIS Integrated mode, you need add to the /configuration/system.webServer/handlers element the following code:
<add name="CssAssetHandler"
path="*.css" verb="GET"
type="BundleTransformer.Core.HttpHandlers.CssAssetHandler, BundleTransformer.Core"
resourceType="File" preCondition="" />
<add name="JsAssetHandler"
path="*.js" verb="GET"
type="BundleTransformer.Core.HttpHandlers.JsAssetHandler, BundleTransformer.Core"
resourceType="File" preCondition="" />
To make AutoprefixCssPostProcessor is one of the default CSS-postprocessors, you need to make changes to the Web.config file. In the defaultPostProcessors attribute of \configuration\bundleTransformer\core\css element must be add AutoprefixCssPostProcessor to end of comma-separated list (for example, defaultPostProcessors="UrlRewritingCssPostProcessor,AutoprefixCssPostProcessor").
In addition to what #Taritsyn said you need to make sure your bundles are
CustomScriptBundle() and not ScriptBundle()
If not you will get the slightly confusing error message:
Could not find the transformer in the '~/Content/css/myCssBundle' bundle.
I found it interesting to look deeper into how this actually works
The HTML is written (just view source) with an additional parameter ?bundleVirtualPath
/Content/css/defenderrazor_DEBUG.less?
bundleVirtualPath=~%2fContent%2fcss%2fmyCssBundle
This is intercepted by the handler in the web.config when a .less file is requested and the handler is then able to use that bundle name to look up any transformations that you've set - including in this case the default post processor for AutoprefixCss.

Sharepoint MySite: Redirecting the Quick launch url

I'm personalizing the MySite page with a custom controller and custom aspx, based in the original ones inside the SPSMSITEHOST folder. What I've done is copy them in my project, create a new controller .ascx and modify the copy of person.aspx and conten.aspx. Then I indicate in the the onet.xml the new path for my pages this way:
<NavBar Name="$Resources:spscore,SubNavTab_Overview_Text;" Url="person.aspx" />
<NavBar Name="$Resources:spscore,SubNavTab_Content_Text;" Url="personcontent.aspx" />
<NavBar Name="$Resources:spscore,SubNavTab_Tags_Text;" Url="_layouts/CustomMySite/thoughts.aspx" />
<NavBar Name="$Resources:spscore,SubNavTab_Colleagues_Text;" Url="_layouts/CustomMySite/MyContactLinks.aspx" />
<NavBar Name="$Resources:spscore,SubNavTab_Memberships_Text;" Url="_layouts/CustomMySite/MyMemberships.aspx" />
The thing is everything is working great. Every element in the quick launch menu is pointing to the right custom url and everything. Everything works great BUT the personcontent.aspx and I'm turning crazy here. The person.aspx is loaded in the same way and it works, why doesn't the personcontent.aspx? Should I change the url somewhere else?
Thanks!
I got with the problem. The url's are ok, but not the file type. It's necessary to mark them as Ghostable
<Modules>
<Module Name="Default">
<File Url="personcontent.aspx" Type="Ghostable"></File>
<File Url="blog.xsl"></File>
<File Url="tagprofile.aspx" Type="Ghostable">
<AllUsersWebPart WebPartZoneID="LeftZone" WebPartOrder="1">
...
This made the trick for me.

Adding my own page to a subtext application

I've just installed subtext and am intending on hosting on discountasp.net. I want to add my own pages to the application (just 3) but if I add a standard aspx I get a 404. I'd ideally like to have a masterpage that uses some of the list controls in subtext so I can keep a list of Recent Posts and Archive on the side bar. It's an ideal, otherwise I could create a couple of my own controls to drop into the page to replicate IF that's not possible.
Any ideas?
Note: This applies to Subtext 2.1.2 and below
You'll need to add a handler mapping in web.config. Subtext tries to handle all requests.
The easiest thing to do is to create a directory where you want all your custom pages to live and map a PageHandlerFactory for that directory.
For example, search for the following in web.config
<add verb="*" path="HostAdmin/*.aspx" type="System.Web.UI.PageHandlerFactory"/>
And add the following line after
<add verb="*" path="custompages/*.aspx" type="System.Web.UI.PageHandlerFactory"/>
In the upcoming Subtext 2.5, you won't need to do this. You can simply drop your page anywhere in a directory and it'll just work.

Reference app relative virtual paths in .css file

Assume I have an "images" folder directory under the root of my application. How can I, from within a .css file, reference an image in this directory using an ASP.NET app relative path.
Example:
When in development, the path of ~/Images/Test.gif might resolve to /MyApp/Images/Test.gif while, in production, it might resolve to /Images/Test.gif (depending on the virtual directory for the application). I, obviously, want to avoid having to modify the .css file between environments.
I know you can use Page.ResolveClientUrl to inject a url into a control's Style collection dynamically at render time. I would like to avoid doing this.
Unfortunately Firefox has a stupid bug here... the paths are relative to the path of the page, instead of being relative to the position of the CSS file. Which means if you have pages in different positions in the tree (like having Default.aspx in the root and Information.aspx in the View folder) there's no way to have working relative paths. (IE will correctly solve the paths relative to the location of the CSS file.)
The only thing I could find is this comment on http://www.west-wind.com/weblog/posts/269.aspx but, to be honest, I haven't managed to make it work yet. If I do I'll edit this comment:
re: Making sense of ASP.Net Paths by
Russ Brooks February 25, 2006 # 8:43
am
No one fully answered Brant's question
about the image paths inside the CSS
file itself. I've got the answer. The
question was, "How do we use
application-relative image paths
INSIDE the CSS file?" I have long been
frustrated by this very problem too,
so I just spent the last 3 hours
working out a solution.
The solution is to run your CSS files
through the ASPX page handler, then
use a small bit of server-side code in
each of the paths to output the root
application path. Ready?
Add to web.config:
<compilation debug="true">
<!-- Run CSS files through the ASPX handler so we can write code in them. -->
<buildProviders>
<add extension=".css" type="System.Web.Compilation.PageBuildProvider" />
</buildProviders>
</compilation>
<httpHandlers>
<add path="*.css" verb="GET" type="System.Web.UI.PageHandlerFactory" validate="true" />
</httpHandlers>
Inside your CSS, use the Request.ApplicationPath property
wherever a path exists, like this:
#content {
background: url(<%= Request.ApplicationPath
%>/images/bg_content.gif) repeat-y;
}
.NET serves up ASPX pages with a MIME type of "text/html" by default,
consequently, your new server-side CSS
pages are served up with this MIME
type which causes non-IE browsers to
not read the CSS file correctly. We
need to override this to be
"text/css". Simply add this line as
the first line of your CSS file:
<%# ContentType="text/css" %>
In case you didn't know you could do this...
If you give a relative path to a resource in a CSS it's relative to the CSS file, not file including the CSS.
background-image: url(../images/test.gif);
So this might work for you.
Make you life easy, just put images used in your CSS in the /css/ folder alongside /css/style.css. Then when you reference your images, use relative paths (e.g. url(images/image.jpg)).
I still keep images that are displayed with a <img> in an /images/ folder. Photos for example are content, they are not part of the website's skin/theme. Thus, they do not belong in the /css/ folder.
Marcel Popescu's solution is using Request.ApplicationPath in the css file.
Never use Request.ApplicationPath - it is evil! Returns different results depending on the path!
Use the following instead.
background-image: url(<%= Page.ResolveUrl("~/images/bg_content.gif") %>);
Put your dynamic CSS in a user control in an .ascx file and then you do not need to run all your css files through the asp.net page processer.
<%# Control %>
<style type="text/css>
div.content
{
background-image:(url(<%= Page.ResolveUrl("~/images/image.png") %>);
}
</style>
But the easiest way to solve the ~ problem is to not use a ~ at all. In Visual Studio, in Solution Explorer, right click your application, select Properties Window and change the Virtual Path to /.
On Windows 7, IIS 7.5:
Not only do you have to do the steps mentionned by Marcel Popescu.
You also need to add a handler mapping in IIS 7.5 handler mappings. So that IIS knows that *.css must be used with the System.Web.UI.PageHandlerFactory
It's not enough to just set the stuff in the web.config file.
Inside of the .css file you can use relative paths; so in your example, say you put your css file in ~/Styles/mystyles.css. You can use url(../Images/Test.gif) as an example.
I was having difficulty in getting background images to display for content containers and have tried many solutions similar to other posted here. I had set the relative path in the CSS file, set it as a style on the aspx page I wanted the background to display - nothing worked. I tried Marcel Popescu's solution and it still didn't work.
I did end up getting it to work following a combination of Marcel's solution and trial and error. I inserted the code into the web.config, inserted the text/css line into my CSS file but I removed the background property in the CSS file altogether and set it as a style on the content container in the aspx page I wanted the background to display.
It does mean that for each or any other pages that I want to display the background I will need to set the style background property but it works beautifully.

Resources