How to check if file exist in ASP.NET MVC 4 - c#

I am working on an ASP.NET MVC 4 application. I allow users to upload files but I want to save them with different name on the server so I created helper method which should return GUID to be used. Even though it probably will never happen still I want to check if I have a file with the same GUID name so I have this as code :
public static string GetUniqueName(string pathToFile)
{
bool IsUnique = false;
string guid = null;
while (!IsUnique)
{
guid = Guid.NewGuid().ToString("N");
var path = System.IO.Path.Combine(pathToFile, "login.jpg");
if (!System.IO.File.Exists(path))
{
IsUnique = true;
}
}
return guid;
}
as you can see the name of the file is hard coded just for testing purposes, because I know there is such file.
To save the file I use this:
var path = System.IO.Path.Combine(Server.MapPath("~/Content/NewsImages"), fileName);
and it's working properly. So when I tried to call my static method I pass the arbument like this:
string test = Helper.GetUniqueName("~/Content/NewsImages");
but then in debug I saw that
System.IO.Path.Combine(pathToFile, "login.jpg");
returns ~/Content/NewsImages\\login.jpg so I decided to change the argument that I pass to:
string test = Helper.GetUniqueName("~\\Content\\NewsImages");
which now results in ~\\Content\\NewsImages\\login.jpg which seems fine but then in:
if (!System.IO.File.Exists(path))
{
IsUnique = true;
}
I pass the check, even though I know that such a file exist in the directory that I want to check. How can I fix this?

When calling the helper method you should use Server.MapPath, this will convert from a virtual path to a physical path e.g.
string test = Helper.GetUniqueName(Server.MapPath("~/Content/NewsImages"));

Related

C# - Using File.Exists, when file DOESN'T exist does not run the last else statement

Super new to C#. I'm having an input get split and then find an ID from the pointsTarget var.
When the file DOES exist, it seems that the line
else if (File.Exists(filePath+userId+txt))
returns true;
because it runs just fine and sets the argument "addPointsCompleted" to TRUE. It works just how I would expect. But when the file does NOT exist, I want it to return false and run the last else statement:
CPH.SetArgument("missing", "True");
and set "missing" to TRUE.
I feel like there is something wrong with the way I put in the if/else if/else statement because I get an error :
"System.IO.FileNotFoundException: Could not find file 'E:\Users\Troy\Documents\Stuff\PointNames\Test.txt'.
using System;
using System.IO;
public class CPHInline
{
public bool Execute()
{
string rawInput = args["rawInput"].ToString();
string[] split= rawInput.Split('+');
var pointsTarget = split[0].ToString();
var addPoints = split[1].ToString();
CPH.LogInfo($"pointsTarget is {pointsTarget}");
CPH.LogInfo($"addPoints is {addPoints}");
var user = args["user"].ToString();
CPH.SetArgument("pointsTarget", pointsTarget);
string userPath = #"E:/Users/Troy/Documents/Stuff/PointNames/";
string filePath = #"E:/Users/Troy/Documents/Stuff/PointIDs/";
string txt = ".txt";
var userId = File.ReadAllText(userPath+pointsTarget+txt);
CPH.LogInfo($"userId is {userId}");
if (user == pointsTarget)
{
CPH.SetArgument("corrupt", "True");
}
else if (File.Exists(filePath+userId+txt))
{
//DO THIS
string fileName = filePath+userId+txt;
string points = File.ReadAllText(fileName);
int x = Convert.ToInt32(points);
int y = Convert.ToInt32(addPoints);
int sum = x + y;
String newPoints;
newPoints = sum.ToString();
File.WriteAllText(fileName, newPoints);
CPH.SetArgument("newPoints", newPoints);
CPH.SetArgument("addPointsCompleted", "True");
}
else
{
//do this
CPH.SetArgument("missing", "True");
}
return true;
}
}
I tried looking around, but all the issues are from people where the file DOES exist and they can't find it. My problem is kind of the opposite.
I feel like there is something wrong with the way I put in the if/else if/else statement because I get an error "System.IO.FileNotFoundException: Could not find file 'E:\Users\Troy\Documents\Stuff\PointNames\Test.txt'.
This is a good opportunity for you to start familiarizing yourself with using a debugger to step through the code and observe its behavior. Because the problem has nothing to do with your if structure. It's happening before your if block. Right here:
var userId = File.ReadAllText(userPath+pointsTarget+txt);
Look at the error message. It's trying to read a file in the "PointNames" folder. Which is in your userPath variable:
string userPath = #"E:/Users/Troy/Documents/Stuff/PointNames/";
Which is only ever used in that one line of code that tries to read a file. And File.ReadAllText will throw a FileNotFoundException if the file is not found.
It seems you're already aware of how to check if a file exists. So why not apply that here? For example:
var userId = string.Empty;
if (File.Exists(userPath+pointsTarget+txt))
{
userId = File.ReadAllText(userPath+pointsTarget+txt);
}
else
{
// handle the error in some way
}

Get source file location with DeterministicSourcePaths turned on

Question:
Is there a way how to get the Caller or current frame source code location without using the CallerFilePath attribute?
Background:
I have this helper defined:
public class PathHelper
{
public static string GetThisFilePath([CallerFilePath] string path = null)
{
return path;
}
}
That can be called as follows to obtain the location of source code used to build the binary:
var currentSourceFilePath = PathHelper.GetThisFilePath();
This works fine, unless I have DeterministicSourcePaths turned on (typically via ContinuousIntegrationBuild msbuild property). In such a case the returned paths are trimmed to something like:
/_/MyRelativeSourcePath
So it seems that determinist paths are injected into the compiler functionality supporting CallerFilePath yielding this behavior.
I need the source code location in order to be able to unit test product specific functionality (that has to do with inspecting build process), while I'd still like to support fully determinisitc build on CI machines.
You may try something like following. Please note
this is just an idea, exact implementation depends on your environment
This would be working if you are using "default build output paths" only
I didn't tested it
public static string GetThisFilePath([CallerFilePath] string path = null)
{
const string determenisticRoot = "/_/";
if(!path.StartsWith(determenisticRoot))
{
return path;
}
// callerBinPath would be something like $(SolutionRoot)/.../MyProject.Tests/bin/Debug/net5.0
var callerBinPath = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
// Traverse to $(TestProjectRoot) - testProjectRoot would be something like $(SolutionRoot)/.../MyProject.Tests
var testProjectRoot = Path.Combine(callerExecutablePath, "../../..");
// Combine projectRoot root with relative path from [CallerFilePath]
return Path.Combine(testProjectRoot, path.Substring(determenisticRoot.Length));
}

Appending chat history and insert it into the same file

I have a case that I need to log the chat history (I am capable of doing this already) and I need it to be logged in a text file (able to log it already).
The problem is the file is being accessed all over again so I need to somewhere store the filename of the file somewhere else, right now I have this code:
public async Task LogAsync(IActivity activity)
{
var conversation = "";
var convActivity = "";
var ctr = 0;
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\r\n Message: {activity.AsMessageActivity()?.Attachments}\r\n ";
fileName = "test";
await LogActivity(fileName, conversation);
}
The LogActivity is the one handling the append of the file. So what I need is I want the unique fileName to be instantiated once while appending the file all over again or rather while continuously accessing this method.
Or is there a way to log the chat history of bot once like if a Context.Done was called or before it?
Or the inefficient way I am thinking of was making use of .From.Name and .Recipient.Name
So the result will be:
if (activity.From.Name.ToLower().ToString() == "user")
{
name.Value = $"{activity.From.Name.ToString()}";
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\n Message: {activity.AsMessageActivity()?.Text}\n";
}
else
{
name.Value = $"{activity.Recipient.Name.ToString()}";
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\r\n Message: {activity.AsMessageActivity()?.Text}\r\n ";
}
await LogActivity(name.Value, conversation);
If I understand correctly, you just want to persist a value throughout a conversation; in this case a filename.
If that's correct, then you can store it in PrivateConversationData which lives in thecontext.
For example:
context.PrivateConversationData.SetValue<string>("log_filename", "log-name-here.txt");
For an example, check here: https://www.robinosborne.co.uk/2016/08/08/persisting-data-within-a-conversation-with-botframeworks-dialogs/
For a full example about persisting the whole conversation, this might also help: https://www.robinosborne.co.uk/2016/11/22/transcribing-messages-in-botframework/
Okay, rposbo's answer also works if you have your own logger (that's what I observed, or maybe if you can implement it the other way around, you can use it, it's up to you) that will persist on each every conversation you have with your bot, see the link he provided on how to persist the whole conversation. As for my end, I used dictionary to store the filename. So down below is what I did
public string _Name { get { return name; } }
string name;
public static Dictionary<string, string> fileName = new Dictionary<string, string>();
public void SetFileName(string _fileName)
{
var isCached = fileName.TryGetValue("filename", out name);
if (!isCached)
{
name = $"{_fileName}_{DateTime.Now.Ticks}";
fileName.Add("filename", name);
}
}
Btw, can I accept two answers? since rposbo's answer also works, but it just doesn't fit for me.

Correct way to use String enums in C#

Let's say I have a directory with a set of XML files (for example, two files called ReadMacAddress.xml and ReadManufacturerId.xml) that I need to handle each one in a special way. Basically each of these XML files are a set of commands that are being received by my class.
Suppose I have an external class that is giving commands about which file should be opened,
public static void test()
{
string RecievedCommand = "ReadMacAddress"; //Command recieved from a queue
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
string xml = File.ReadAllText(baseDirectory + "ReadMacAddress.xml");
}
To have the possibility of opening the file automatically based on which command is received I was thinking of doing the following, first defining an enum data structure with the names of the files and then using a switch case to differentiate between the different commands(name of the file that needs to be parsed) and then using this while parsing the file.
class My_EnumXML
{
public enum ReadXML
{
ReadMacAddress,
ReadManufacturerId,
}
}
class TestRead
{
public static void OpenFile()
{
string RecievedCommand = "ReadMacAddress";
string CurrentCommand = SMLReadInputs((My_EnumXML.ReadXML)RecievedCommand);
string xml = File.ReadAllText(baseDirectory + CurrentCommand);
}
public string SMLReadInputs(My_EnumXML.ReadXML pRecievedCommand)
{
string CurrentCommand = "";
switch (pRecievedCommand)
{
case My_EnumXML.ReadXML.ReadMacAddress:
CurrentCommand = Enum.GetName(typeof(My_EnumXML.ReadXML), 0);
case My_EnumXML.ReadXML.ReadMacAddress:
CurrentCommand = Enum.GetName(typeof(My_EnumXML.ReadXML), 0);
}
return CurrentCommand;
}
}
For this example I just used the name of two XML files but I have a 100 of these and I need to know if I am proceeding in the right way, especially since I cannot debug my code because the part about receiving commands from a message queue is being implemented by someone else.

IIS Application : How to get an unique ID

I have an application that manage IIS Application instances so I am looking for a kind of GIUD to identify each applications. This GUID must be created when the application is deployed in IIS and must be persistent to IIS/Windows updates/restarts.
I did not need the use of Microsoft.Web.Administration: I want a simple way, for each IIS application, it returns its unique ID (by a method called within it).
Here is an example of what I'm looking for and I'd like to have an unique id returned by this.????? :
public class MvcApplication : System.Web.HttpApplication
{
string myUniqueID {
get { return this.?????; }
}
}
Thanks for help.
HostingEnvironment.ApplicationID
https://msdn.microsoft.com/en-us/library/system.web.hosting.hostingenvironment.applicationid(v=vs.110).aspx
I had to do something similar.
Read the web.config file for a HostId setting. Preferably split your configuration file into two, with one config file that is local to the install, and doesn't get replaced upon upgrading to a new version of the website.
If the HostId value doesn't exist in the web.config, call Guid.NewGuid() to generate a new value.
Save the new value to the web config, preferably in the local section/file.
Return the value.
Here is some psuedo-code:
public Guid HostId
{
get
{
var result = GetSetting(ConfigFileLocalSettingList.HostId).TryToGuid();
if (result == null)
{
result = Guid.NewGuid();
SetSetting(ConfigFileLocalSettingList.HostId, result.ToString());
Save();
}
return result.Value;
}
}
You can use the assembly GUID for this purpose: In AssemblyInfo.cs, you can find
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("307E39B9-2C41-40CF-B29F-84C8BBCD6519")]
To read this value, you can use:
public static string AssemblyGUID
{
get {
var assembly = Assembly.GetExecutingAssembly();
var attribute = (System.Runtime.InteropServices.GuidAttribute)assembly.GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true)[0];
var GUID = attribute.Value;
return GUID;
}
}
which is taken from another SO answer (you can find it here).
And if it is required, Visual Studio allows you to create a new GUID via menu Tools -> Create GUID - if you need a different one.
Or in C# you simply use
var newGuid=(Guid.NewGuid()).ToString();
Console.WriteLine(newGuid);
to create a new GUID.

Categories

Resources