Combining System.IO.Path and System.Uri into a complete system path - c#

Im writing a small web interface for my application and am getting hung on combining a known docs path and the request URI into a absolute local path to retrieve the file from.
For simplicity sake I narrowed my code down to the relevant:
string AssemblyDirectory = "C:\MyAppDir\";
string uri = "/index.html";
return new Uri(new Uri(Path.Combine(AssemblyDirectory, "http_docs")), uri).AbsolutePath;
This will always just return the uri portion only; ie the return is "/index.html", it does not seem to like to combine types of Uri and Path properly. I am aware that simply replacing the "/"'s with "\"'s then doing a simple path.combine would work fine, but I cant help but think there is a .net solution to this somewhere that I am overlooking.

The matter is that you have a / before your index.html. It makes the Uri API to refer to the root of the uri, which gives you at last : c:\index.html.
Remove the / in uri to make it work :
string uri = "index.html";

Related

Allowing full file path in URI for Web API call

I am currently working on a 'download file' implementation using Web API 2.
However, as the files that can be downloaded are NOT stored in the database, I am passing in the full file path as the parameter for identification.
It seems the problem with this approach is that the filePath contains characters that are invalid for a URI... Has anyone got any suggestions to resolve this or an alternate approach?
Download file method:
[HttpGet]
[Route("Files/{*filePath}")]
public HttpResponseMessage Get([FromUri]string filePath)
{
try
{
var file = new FileInfo(filePath);
byte[] bytes = System.IO.File.ReadAllBytes(filePath);
var result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = file.Name + file.Extension;
return result;
}
catch(Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
}
}
Requiring the client to put the full path in the URI (even if it were encoded so that it only contains valid characters for the URI) implies that you may be publishing these paths somewhere... this is not a great idea for a few reasons:
Security - full Path Disclosure and associated Relative Path Traversal
i.e. what's to stop someone passing in the path to a sensitive file (e.g. your web.config file) and potentially obtaining information that could assist with attacking your system?
Maintainability
Clients may maintain a copy of a URI for reuse or distribution - what happens if the file paths change? Some related conversation on this topic here: Cool URIs don't change
My suggestion - you don't have to put the files themselves in a database, but put a list of files in a database, and use a unique identifier in the URL (e.g. perhaps a slug or GUID). Look up the identifier in the database to discover the path, then return that file.
This ensures:
Nobody can read a file that you haven't indexed and determined is safe to be downloaded
If you move the files you can update the database and client URIs will not change
And to respond to your original question, you can easily ensure the unique identifier is only made up of URI safe characters
Once you have the database, over time you may also fine it useful to maintain other metadata in the database such as who uploaded the file, when, who downloaded it, and when, etc.

How to get URL of a resource in visual studio c#?

I am making a simplePlayer WindowsForm. In order for the video to play i need to provide the url
axWindowsMediaPlayer1.URL = #"C:\Users\Stephan\Desktop\trasa-1250.wmv";
Now i need to either use relative paths or add them as a resource and get the url for that resource but i don't know how to do that:
wplayer.URL = Resources.trasa_1250.
I've tried using
axWindowsMediaPlayer1.URL = #"~\trasa-1250.wmv";
and
axWindowsMediaPlayer1.URL = #".\trasa-1250.wmv";
but printing #"~\trasa-1250.wmv"; and #.\trasa-1250.wmv"; prints them as they are without replacing the ~ or the .
To get the absolute path for a file, by supplying a name relative to the current directory, you can use:
string filename = "trasa-1250.wmv";
string path = Path.GetFullPath(filename);
For completeness sake, to create an actual Url from this:
string url = new Uri(path).AbsoluteUri;
You can't create a Url to an embedded resource, unless you program the player to accept a custom Url scheme (to allow, for instance, "resource://assemblyName.namespace.resourceName") and process it correctly.
A common alternative is to let the caller provide the Stream from which to read the media - and let them decide on how to access the resource.
Here is a tutorial that will help:
https://www.youtube.com/watch?v=nF-HYoTurc8
You could also get the URL like this:
Uri MyUri = new Uri(#"/Resources/trasa-1250.wmv", UriKind.Relative);

ASP.NET MVC Get file from virtual path

For various reasons, in development I occasionally want to intercept a request for, say, ~/MyStyle.css
What I want to do is make the following snippet work:
string absFile = VirtualPathUtility.ToAbsolute(file);
return System.IO.File.ReadAllText(absFile);
This absolute path is absolute for the webserver though, it's not going to map to "C:\whatever". Is there an equivalent method to go to the file system? (Or a ReadFromVirtualPath etc.?)
Use Server.MapPath() to get the file system path for a requested application path.
string absFile = Server.MapPath(file);
or
string absFile = HttpContext.Current.Server.MapPath(file);
You can also use the OpenFile method on VirtualPathProvider to get a Stream pointing at your file
var stream = HostingEnvironment.VirtualPathProvider.OpenFile(file);
var text = new StreamReader(stream).ReadToEnd();
Generally this approach is preferable since you can now, at a later point implement a VirtualPathProvider where, lets say all your css files where located in a database.

URI Class 101 - Relative Project Reference

I know next to nothing about the URI class. I need to make an Relative URI to reference a file in my project (that is on the root of the project).
How can I do that?
This is what I have tried and it does not seem to work:
var uri = new Uri("ModuleCatalog.xaml", UriKind.Relative)
I have also tried:
var uri = new Uri("/ShellProject;component/ModuleCatalog.xaml", UriKind.Relative);
When I examine my uri variable in the debugger it has thrown a lot of exceptions. The only value that is real is the original text value.
What do I need to do to make it a valid uri?
I think that I don't get how a Uri object works.
I guess I am asking for the basics of how to make a uri and have it reference a file in my project (with out having to hard code the full path from the C:\ drive.
Is your application a Web App?
You don't use URIs to reference local files in non-web apps.
The expression
var uri = new Uri("ModuleCatalog.xaml", UriKind.Relative)
Doesn't throw any exceptions on construction, it throws later when it is used improperly.
Since you mentioned you are developing a WPF app, if you want to locate this file you should use:
string assemblyLocation = Assembly.GetExecutingAssembly().Location
string moduleCatalogPath = Path.Combine(assemblyLocation, "ModuleCatalog.xaml");
What does "not work" mean? Both code examples compile and run, giving valid relative URIs.
Or perhaps you want to make absolute URIs from the relative URIs? That is, if your root is "http://example.com", you want to create "http://example.com/ModuleCatalog.xaml". In that case, use the Uri.TryCreate overload that lets you pass in the root. For example:
Uri baseUri = new Uri("http://example.com");
Uri newUri;
if (Uri.TryCreate(baseUri, "ModuleCatalogue.xaml", out newUri))
{
// Uri created successfully
}

Uri.AbsolutePath messes up path with spaces

In a WinApp I am simply trying to get the absolute path from a Uri object:
Uri myUri = new Uri(myPath); //myPath is a string
//somewhere else in the code
string path = myUri.AbsolutePath;
This works fine if no spaces in my original path. If spaces are in there the string gets mangled; for example 'Documents and settings' becomes 'Documents%20and%20Setting' etc.
Any help would be appreciated!
EDIT:
LocalPath instead of AbsolutePath did the trick!
This is the way it's supposed to be. That's called URL encoding. It applies because spaces are not allowed in URLs.
If you want the path back with spaces included, you must call something like:
string path = Server.URLDecode(myUri.AbsolutePath);
You shouldn't be required to import anything to use this in a web application. If you get an error, try importing System.Web.HttpServerUtility. Or, you can call it like so:
string path = HttpContext.Current.Server.URLDecode(myUri.AbsolutePath);
It's encoding it as it should, you could probably UrlDecode it to get it back with spaces, but it's not "mangled" it's just correctly encoded.
I'm not sure what you're writing, but to convert it back in asp.net it's Server.UrlDecode(path). You also might be able to use LocalPath, rather than AbsolutePath, if it's a Windows app.
Just use uri.LocalPath instead
Uri also has a couple of static methods - EscapeDataString and EscapeUriString.
Uri.EscapeDataString(uri.AbsolutePath) also works
Use HttpUtility:
HttpUtility.UrlDecode(uri.AbsolutePath)

Categories

Resources