A problem with Relative Path Resolution when setting an Image Source - c#

I have built a small WPF application that allows users to upload documents and then select one to display.
The following is the code for the file copy.
public static void MoveFile( string directory, string subdirectory)
{
var open = new OpenFileDialog {Multiselect = false, Filter = "AllFiles|*.*"};
var newLocation = CreateNewDirectory( directory, subdirectory, open.FileName);
if ((bool) open.ShowDialog())
CopyFile(open.FileName, newLocation);
else
"You must select a file to upload".Show();
}
private static void CopyFile( string oldPath, string newPath)
{
if(!File.Exists(newPath))
File.Copy(oldPath, newPath);
else
string.Format("The file {0} already exists in the current directory.", Path.GetFileName(newPath)).Show();
}
The file is copied without incident. However, when the user tries to select a file they just copied to display, A file not found exception. After debugging, I've found that the UriSource for the dynamic image is resolving the relative path 'Files{selected file}' to the directory that was just browsed by the file select in the above code instead of the Application directory as it seems like it should.
This problem only occurs when a newly copied file is selected. If you restart the application and select the new file it works fine.
Here's the code that dynamically sets the Image source:
//Cover = XAML Image
Cover.Source(string.Format(#"Files\{0}\{1}", item.ItemID, item.CoverImage), "carton.ico");
...
public static void Source( this Image image, string filePath, string alternateFilePath)
{
try
{image.Source = GetSource(filePath);}
catch(Exception)
{image.Source = GetSource(alternateFilePath);}
}
private static BitmapImage GetSource(string filePath)
{
var source = new BitmapImage();
source.BeginInit();
source.UriSource = new Uri( filePath, UriKind.Relative);
//Without this option, the image never finishes loading if you change the source dynamically.
source.CacheOption = BitmapCacheOption.OnLoad;
source.EndInit();
return source;
}
I'm stumped. Any thought's would be appreciated.

Although I don't have a direct answer, you should use caution for such allowing people to upload files. I was at a seminar where they had good vs bad hackers to simulate real life exploits. One was such that files were allowed to be uploaded. They uploaded malicious asp.net files and called the files directly as they new where the images were ultimately presented to the users, and were able to eventually take over a system. You may want to verify somehow what TYPES of files are being allowed and maybe have stored in a non-exeucting directory of your web server.

It turns out I was missing an option in the constructor of my openfiledialogue. The dialogue was changing the current directory which was causing the relative paths to resolve incorrectly.
If you replace the open file with the following:
var open = new OpenFileDialog{ Multiselect = true, Filter = "AllFiles|*.*", RestoreDirectory = true};
The issue is resolved.

Related

What's the right way to copy a file in another folder?

I have to copy a certain file to another folder, and this has to happen when I click a button.
Now I have two problems: the file is not copied correctly, and the new folder with the new file is created after one or two minutes.
When i say copied incorrectly, I mean that -0.364384 becomes -0.365163223838319.
I'm currently using this script in my button (ps I have three buttons for files named 1.json 2.json and 3.json)
private string path = "Assets\\Modelli\\Sinc ";
public void salvaEs1()
{
if (Directory.Exists(path)) { Directory.Delete(path, true); }
Directory.CreateDirectory(path);
string fileToCopy = "Assets\\Modelli\\daMedico\\1.json";
string destinationDirectory = "Assets\\Modelli\\Sinc\\";
File.Copy(fileToCopy, destinationDirectory + "sinc.json");
}
Errors are about some code that I use to read the file. But the problem are the errors in the file, non the ones that come from them

Tfs Check-in using PendAdd: The array must contain at least one element

So I'm having a problem with automating my code to check-in files to TFS, and it's been driving me up the wall! Here is my code:
string location = AppDomain.CurrentDomain.BaseDirectory;
TfsTeamProjectCollection baseUserTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection);
IIdentityManagementService ims = baseUserTpcConnection.GetService<IIdentityManagementService>();
TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, #"PROD1\JR", MembershipQuery.None, ReadIdentityOptions.None);
TfsTeamProjectCollection impersonatedTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection, identity.Descriptor);
VersionControlServer sourceControl = impersonatedTpcConnection.GetService<VersionControlServer>();
Workspace workspace = sourceControl.CreateWorkspace("MyTempWorkspace", sourceControl.AuthorizedUser);
String topDir = null;
try
{
Directory.CreateDirectory(location + "TFS");
String localDir = location + "TFS";
workspace.Map("$/Automation/", localDir);
workspace.Get();
destinationFile = Path.Combine(localDir, Name + ".xml");
string SeconddestinationFile = Path.Combine(localDir, Name + ".ial");
bool check = sourceControl.ServerItemExists(destinationFile, ItemType.Any);
PendingChange[] pendingChanges;
File.Move(sourceFile, destinationFile);
File.Copy(destinationFile, sourceFile, true);
File.Move(SecondsourceFile, SeconddestinationFile);
File.Copy(SeconddestinationFile, SecondsourceFile, true);
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
else
{
workspace.PendEdit(destinationFile);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
and the problem is that whenever it's NEW files (PendEdit works correctly when the files already exist in TFS) that my code is attempting to check in, and it runs through this code:
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
The files, instead of being in the included changes in pending changes, are instead in the excluded changes like so:
and when the line that actually does the check-in runs, I'll get a "The array must contain at least one element" error, and the only way to fix it is to manually add those detected changes, and promote them to included changes, and I simply can't for the life of me figure out how to do that programatically though C#. If anyone has any guidance on what direction I should take for this, I would really appreciate it! Thank you!
Edit: I've also discovered another way to solve this by reconciling the folder, which also promotes the detected changes, but again the problem is I can't seem to figure out how to program that to do it automatically.
I know that running the visual studio developer command prompt, redirecting to the folder that this mapping is in, and the running "tf reconcile /promote" is one way, but I can only automate that as far as the /promote part, because that brings up a toolbox that a user would have to input into, which defeats the purpose of the automation. I'm at a loss.
Next Edit in response to TToni:
Next Edit in response to TToni:
I'm not entirely sure if I did this CreateWorkspaceParameters correctly (see picture 1), but this time it gave the same error, but the files were not even in the excluded portions. They just didn't show up anywhere in the pending changes (see picture 2).
Check this blog:
The workspace has a method GetPendingChangesWithCandidates, which actually gets all the “Excluded” changes. Code snippet is as below:
private void PendChangesAndCheckIn(string pathToWorkspace)
{
//Get Version Control Server object
VersionControlServer vs = collection.GetService(typeof
(VersionControlServer)) as VersionControlServer;
Workspace ws = vs.TryGetWorkspace(pathToWorkspace);
//Do Delete and Copy Actions to local path
//Create a item spec from the server Path
PendingChange[] candidateChanges = null;
string serverPath = ws.GetServerItemForLocalItem(pathToWorkspace);
List<ItemSpec> its = new List<ItemSpec>();
its.Add(new ItemSpec(serverPath, RecursionType.Full));
//get all candidate changes and promote them to included changes
ws.GetPendingChangesWithCandidates(its.ToArray(), true,
out candidateChanges);
foreach (var change in candidateChanges)
{
if (change.IsAdd)
{
ws.PendAdd(change.LocalItem);
}
else if (change.IsDelete)
{
ws.PendDelete(change.LocalItem);
}
}
//Check In all pending changes
ws.CheckIn(ws.GetPendingChanges(), "This is a comment");
}

Load Image from Embedded resource WP8 / C#

I am trying to load an image from an Embedded resource in a windows phone application
Here is my project setup:
Module1 = Phone Application
Module2 = ClassLibrary.dll
Module1 calls Module2 to create all of the data objects for the phone app.
When Module2 is creating the objects, I wanted to load an image from a resource.
The resource is "Default.png" and saved in the "Images" directory ( Build Action = Embedded Resource, Copy to Output Directory = Copy Always)
The code I am using produces an exception
ex = {"The request is not supported. "}
Here is the code:
private void LoadImage()
{
Assembly curAssembly = null;
curAssembly = Assembly.GetExecutingAssembly();
string [] names = curAssembly.GetManifestResourceNames();
// names[0] = "Storage.Images.Default.png"
// so I know I am using the correct name
Stream resStream = curAssembly.GetManifestResourceStream("Storage.Images.Default.png");
BitmapImage bitMapImage = new BitmapImage();
try
{
bitMapImage.SetSource(resStream);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
Can you help a newbie out?
Thanks
Steps to get that working:
First Appraoch
Right-click on your project in VS and choose "Add New Item"
From "General" tab choose "Resources File"
Open that resource_file.resx which you just added to your project and choose "Add Existing Item" and then choose your image.
Then then in your LoadImage method, do this:
private void LoadImage()
{
Drawing.Bitmap bitMapImage = resource_file.name_of_your_image;
}
Note: In this code, I assumed that the name you choose for your resource file is "resource_file"
Second Approach
System.Resources.ResourceManager rm = new System.Resources.ResourceManager(this.GetType().Assembly.GetName().Name + ".resource_file", this.GetType().Assembly);
System.Drawing.Bitmap bmp= (System.Drawing.Bitmap)rm.GetObject("Baba");
or use can use System.Resources.ResourceReader and other approaches
Figured it out...
The name I was using to load the resource was wrong...
Using the name from the array returned in this call
string [] names = curAssembly.GetManifestResourceNames();
And it works flawlessly

Accessing Resources in a C# WPF Application (Same Assembly)

(Before I jump into the nitty-gritty, I want to set the context: I'm trying to load a WPF frame with the contents of an .html file that I'm including in my project as a resource.)
I create a new WPF Application; I add a new folder called 'foofiles' to the project, and I add a couple of files (page1.foo and page2.foo) to that folder.
For each newly added .foo file, I right-click on it, go to "Properties," and set the Build Action to 'Resource,' and the Copy To Output Directory to "Copy always."
I want to be able to access those files both in XAML:
<Frame x:Name="bar" Source="/foofiles/page1.foo"/>
And in procedural code:
private void someFunc()
{
bar.Source = new Uri("/foofiles/page1.foo");
}
But I just can't figure out why this doesn't work -- I get a "Format of the URI could not be determined."
In the code-behind, I tried doing this:
private void someFunc()
{
bar.Source = new Uri("pack://application:,,,/foofiles/page1.foo");
}
which didn't throw an exception, but my main window crashed.
In my thinking, if I add a file of any type to my project, and if I mark it as "Resource" in "Build Action," I should be able to use that file per my examples above. Also, I would like to use that file like this:
private void someOtherFunc()
{
System.IO.StreamReader reader = new System.IO.StreamReader("/foofiles/page1.foo");
string bar = reader.ReadToEnd();
}
Any help would be appreciated... thanks in advance!
Try adding the component-part to your Pack URI like this
pack://application:,,,/AssemblyName;component/ResourceName
where AssemblyName is the name of your assembly. So for your case, the following statement should work:
bar.Source = new Uri("pack://application:,,,/AssemblyName;component/foofiles/page1.foo");
More practically, try the relative pack uri notation:
bar.Source = new Uri("AssemblyName;component/foofiles/page1.foo", UriKind.Relative));
For stream reading resources use
var streamResourceInfo = Application.GetResourceStream(uri);
using (var stream = streamResourceInfo.Stream)
{
// do fancy stuff with stream
}

how to display image created dynamically in asp.net 3.5 c# on localhost

I have to display image dynamically. I have written code for that, i got the name of the image & path also from database i.e Filename & filepath which i stored earlier, but I didnt get image(not displaying image even i stored path of that image). Please give me idea about how to set imageurl of image here on local host. My code is as follow:
//PlaceHolder for adding images i.e inside formview control
PlaceHolder PHFilename = (PlaceHolder)FVViewCustData.FindControl("PHFilename");
for (int i = 0; i < dsfile.Tables[0].Rows.Count; i++)
{
HyperLink hypname = new HyperLink();
hypname.Text = Convert.ToString(dsfile.Tables[0].Rows[i]["FileName"]);
PHFilename.Controls.Add(hypname);
Image img = new Image();
//IPAddress is my ipaddress
img.ImageUrl = "IPAddress" + Convert.ToString(
dsfile.Tables[0].Rows[i]["FilePath"]);
PHFilename.Controls.Add(img);
}
If you keep the Image data in DB you can use image handler and load dynamically.
But if you keep the image URL in DB depends on what do you save filename or relative path or absolute path.
C# Save and Load Image from Database
There are couple of ways to solve your issues:
First Way:
Store all your images under some base directory - you can have sub-directories under it. The image path that you store in the database will be relative to this base directory. Now map this base directory as some virtual directory in your web site. Now you can use code such as
string imageVirtualDir = "/StoredImages/";
img.ImageUrl = imageVirtualDir + Convert.ToString(
dsfile.Tables[0].Rows[i]["FilePath"]);
Needless to say, base directory path and image virtual directory path will be configurable values.
Second Way:
You can store images wherever you wish. Let's say you get the complete physical path from the database. So you will set the image url such as
img.ImageUrl = "/ImageServer.ashx?path=" + Convert.ToString(
dsfile.Tables[0].Rows[i]["FilePath"]);
Here, you will need a simple http handler (ImageServer.ashx) to serve your images - the code will be something like
public class ImageServer : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var path = context.Request["path"];
context.Response.ContentType = "image/jpeg";
context.Response.TransmitFile(path);
}
public bool IsReusable
{
get
{
return false;
}
}
}
Note that this is just a template code to get you started. For production code, you need to have error handling, setting correct content type as per image type. Also, its not advisable to have physical image path in query string - so you need to pass either relative path or some token instead - for example, you can pass the row id so that your handler can query database and get the image path etc.

Categories