Calculating Relative Path Change - c#

Assuming I have a .css file with the following line
body { background-image: url('../images/bg.png') }
My build process does some CSS magic and eventuall move this file from
~/Content/styles/styles.css
To
~/temp/styles.css
This invalidates the url statement in the file and needs re-written to ../Content/images/bg.png
This is my question - given the original file location, the new file location and the background-image url in the file is there a reusable way calculate a new relative path for the image?
In case someone doesn't know css urls should be relative to the css file it is contained within.

Solution 1
If you use ASP.NET themes, you can work around this issue. However, it also means you will have to restructure the way your files are.
Simply add a an App_Themes folder and a folder below that with a theme name ('Default' would be a good choice for a site with only 1 theme).
Add your theme name to the <pages> element in web.config:
<pages theme="Default">
Then put your css file inside of the theme folder. REMOVE any code that you use to reference the css file because ASP.NET will automatically wire it up to all of your pages.
If you want more control over the pages you add the css to, you can simply add the theme to the #page directive on the pages or do it in code behind in your base page in the Page_PreInit event instead of the web.config file.
Now, if you also put images below your theme folder, they can be referenced like this from css:
background-image: url('Images/Buttons/login-sprite.gif');
This example assumes your image file is in the location
[AppFolder]/App_Themes/Default/Images/Buttons/login-sprite.gif
and your css file is in the location
[AppFolder]/App_Themes/Default/Styles.css
Solution 2
If you prefer not to rearrange your files, you can also dynamically generate the file or read it into a string and replace a token of your choosing (example #MyImageFile#) with the actual url after calling ResolveUrl to make sure it is correct.
You could put code such as this in a file named Styles.aspx:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'This is a wrapper for the CSS file that allows us to inject
'any image URLs directly into the file, accounting for any relative
'path differences between different environments.
Dim FileName As String = Server.MapPath("Styles.css")
Dim sr As StreamReader
Dim contents As String
sr = File.OpenText(FileName)
Try
contents = sr.ReadToEnd
Finally
sr.Close()
End Try
'Now that we have the contents of the file, run our
'function on it to replace the tokens
contents = Me.ProcessConfigurationTokens(contents)
Response.Clear()
Response.AddHeader("content-type", "text/css")
Response.Write(contents)
Response.End()
End Sub
And then change your page references from Styles.css to Styles.aspx.
There is a performance hit with this approach, but it could be offset using caching. However, I think using Themes is the best approach because it solves the problem using the framework alone without writing any extra code.

You might consider using less to describe the image-path in a variable (pre-generating this as part of the build). Then you only have one thing to update?

Related

How to create PDF file links with relative file path and PDFsharp?

My App creates a Content.pdf file that links to Server.pdf and Client.pdf. This is the folder structure:
..\MyApp\Ressources\Content.pdf
..\MyApp\Ressources\Server\Server.pdf
..\MyApp\Ressources\Client\Client.pdf
Furthermore, the folders and files get burned on a CD/DVD or get backed up on a network drive - that causes me to use relative file paths. I use following code to create the Content.pdf:
relative WebLink:
var relativeFileLinkPath = "./" + Directory.GetParent(doc.Uri.LocalPath).Name + "/"+ doc.OutputFileName;
page.AddWebLink(pdfrect, relativeFileLinkPath);
relative FileLink:
var relativeFileLinkPath = "./" + Directory.GetParent(doc.Uri.LocalPath).Name + "/"+ doc.OutputFileName;
page.AddFileLink(pdfrect, relativeFileLinkPath);
Both work fine on local drive, but my issues are:
WebLinks do not work/open on network drive
FileLinks close the Content.pdf and replace it with the linked pdf file
Questions:
How can I modify the FileLinks to get opened in a new (PDF reader) instance/window?
Holding the CTRL-Key when clicking on the FileLink is an option but not a nice solution.
What’s the right syntax for relative PDF web links?
AddFileLink is the correct method for files sitting side by side in a folder.
To control whether a new window will be opened, a small modification of PDFsharp's PdfLinkAnnotation class will be needed. PDF supports a NewWindow attribute which PDFsharp cannot currently set.
Get the source for PDFsharp, locate "<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>" in PdfLinkAnnotation.cs and replace it with "<</Type/Action/S/Launch/NewWindow true/F<</Type/Filespec/F{0}>> >>".
Disclaimer: I did not test the proposed change - I hope it is syntactically correct and I hope it does what you want.
Disclaimer 2: This change is needed for PDFsharp 1.50 beta 3. Later versions may have support for that flag.

How can I add images into my .resx file?

By other than using AddResource button of Visual Studio, of course.
I submit a form, and an image file with it. In my controller action, I get the HttpPostedFileBase object, and its file name by using Path.GetFileName(). If I just use SaveAs() function to save the image file in my application, I cannot access it later for testing, because it gives me the "Not allowed to load local resource" error.
So I want to add the image to a .resx file and retrieve it later using ResourceManager or something. My question is, how can I add the image I have in the controller action into my .resx file?
I should also ask if this is the good approach for the purpose of adding and retrieving image files in my application.
EDITED:
Ok, using .resx to store images is not a good idea. My original problem was that I could save the image file, but when I tried to show it in my view, it gives "Not allowed to load local resource" error.
Here's the controller code:
public ActionResult UrunEkle(Urun urun, HttpPostedFileBase image)
{
Directory.CreateDirectory(Server.MapPath("~/App_Data/Images"));
var path = Path.Combine(Server.MapPath("~/App_Data/Images"), fileName);
image.SaveAs(path);
urun.ArtUrl = path;
// other stuff....
}
And in my view, I try to retrieve the image like this:
<img alt="#urun.name" src="#Url.Content(urun.ArtUrl)" />
But using Google Chrome, I get this "Not allowed to load local resource". How can I avoid this?
Forget trying to add the image to a RESX file; it's not designed to be modified at runtime.
Please post some code. The most likely thing is that the URL that you're serving up to use the image later is incorrect. Probably because you're returning the path of the file on the server, not a URL to the image within the context of the web site.
The error message from Chrome is telling you that it's trying to load a resource from the local file system on the client.
Url.Content converts a relative virtual path into an absolute virtual path and needs a URL starting with ~. You're currently passing in the absolute physical path to the image file and Url.Content is returning it, unchanged. You need the relative virtual path (~/App_Data/Images/Untitled.png) in urun.ArtUrl. This is the value that you passed in to Server.MapPath.

How to load css into html dynamically?

My C# program uses a web browser control and I programmatically set its html property by laoding it from a html string variable. This almost works well ,but I noticed it lost the reference to the css file. I think a simplest solution is to make the path of the css file absolute,but I want it remains relative to the C# executable.So let me ask how to let the html reference to the css file in such a context.
Thank you in advance.
Edit: I am sorry . My c# application is a desktop one ,although it uses a web browser control.
Edit: Let me put some code. I first load the document from an html file then store it in a variable then for the 2nd time or later I load the document from the variable.
//first load
web_browser_control.Url = new Uri( dir + #"\HTML\default1.html" );
void wB2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{ html_string = web_browser_control.DocumentText; }
//second load or later
web_browser_control.DocumentText = html_string;
You need to have a look at what path it THINKS its resolving, it would be best if you could please include some code, chances are its not resolving to where you think it is as its executing out of the bin directory (is your path correct relative to the path of the executable and the html),
For example is the html its looking at still where you think it is or is it now in a different directory so the relative paths are now obsolete ?
More code would be good and an indication of the control you are using.
Seems you can change property of css file to be "content" and make property "copy to output directory" - "always", so the wep app dll will be in the same directory with css file.
Or you can use MapPath method.

Checking if image exist in my local resources

net/C# application I have list of items.
In the code behind:
I want to assign a picture from my local resources for each item. the items name and the picture names are the same.
The pictures are all in a "image" folder in my project.
Example of how I assign a picture to an item:
Item1.PictureUrl = "images/items/" + item1.Name + ".jpg";
I have items that don't have pictures. I want to assign for them a default picture.
I tried to check if the picture exists using this:
foreach(ObjectItem item in ListOfItems)
{
if(File.Exists("images/items/"+item.Name+".jpg"))
item.PictureUrl = "images/items/"+item.Name+".jpg";
else
item.PictureUrl= "images/Default.jpp";
}
But the File.Exists method is always returning false, even if the picture exist.
I also tried to use '\' instead of '/' but didn't work
How can I do it?
Thank you for any help
You need to convert the relative file path into a physical file path in order for File.Exists to work correctly.
You will want to use Server.MapPath to verify the existence of the file:
if(File.Exists(Server.MapPath("/images/items/"+item.Name+".jpg")))
Also, when you use Server.MapPath, you should usually specify the leading slash so that the request is relative to the web application's directory.
If you don't provide the leading slash, then the path will be generated relative to the current page that is being processed and if this page is in a subdirectory, you will not get to your images folder.
.Net Core Solution
1- Write this at the top of your View (Injecting IHostingEnvironment here);
#inject Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnv
2- Write this to the place of image(Doing existence check);
var path = System.IO.Path.Combine(hostingEnv.WebRootPath, "MyFolder", "MyImage.jpg");
if (System.IO.File.Exists(path))
{
<img class="img-fluid" src="~/MyFolder/MyImage.jpg" alt="">
}
var path = $#"C:\Fotos\Funcionarios\1.Png";
FileInfo file = new FileInfo(path);
if (file.Exists.Equals(true))
{
//faz algo
}

Loading FlowDocument.xaml that is part of my solution

I created a FlowDocument.xaml in my current WPF project. What i want to do is when the user clicks a button the XAML document will be loaded in the code behind, have some data on the document modified, and then print it out. The sticking point is i don't know how load the flow document so that i can modify it.
When I do:
FileStream fs = File.Open("FlowDocument.xaml", FileMode.Open)
It says that it can't find the file. The file is part of the project and I'm guessing it gets packaged with the rest of the project when compiled.
Any help is appreciated
Assuming it is configured to be a Resource, then you can load it like so:
FlowDocument doc= Application.LoadComponent(new Uri("/Path/FlowDocument.xaml", UriKind.RelativeOrAbsolute)) as FlowDocument;
This looks like it might be a path/relative path issue...just for testing purposes, try specifying the entire physical/absolute path in the File.Open statement...
You could also do
string path = Directory.GetCurrentDirectory();
to check to see what the current directory is and then make sure that the file FlowDocument.xaml is in that directory

Categories

Resources