ReSharper "Possible NullReferenceException" wrong with FileInfo? - c#

I just started using ReSharper and I'm trying to identify why it thinks this code is wrong.
var file = new FileInfo("foobar");
return file.Directory.FullName;
It highlights file.Directory as a "Possible System.NullReferenceException". I'm not sure how this is possible because the file object can never be null and I can't figure out how the DirectoryInfo object returned from the FileInfo object could ever be null.

The Directory property can indeed be null. The implementation of the property is roughly
public DirectoryInfo Directory {
get {
string directoryName = this.DirectoryName;
if (directoryName == null) {
return null;
}
return new DirectoryInfo(directoryName);
}
}
It can definitely return null. Here is a concrete example
var x = new FileInfo(#"c:\");
if (x.Directory == null) {
Console.WriteLine("Directory is null"); // Will print
}

Related

Why does t.GetProperty always return null?

I'm coding an app using Visual Studio and Xamarin in C#, and I'd like the user to be able to take a photo and save it in his phone to later be retrieved within the app. To do this, I need to start by saving the photo in the phone. My photos are of type FileResult and I put all the photos in a list and save the list thanks to this block of code:
public static List<FileResult> SavedListPhoto
{
get
{
var savedList = Deserialize<List<FileResult>>(Preferences.Get(nameof(SavedListPhoto), null));
Console.WriteLine(savedList);
return savedList ?? new List<FileResult>();
}
set
{
var serializedList = Serialize(value);
Preferences.Set(nameof(SavedListPhoto), serializedList);
Console.WriteLine(nameof(SavedListPhoto));
}
}
static T Deserialize<T>(string serializedObject) => JsonConvert.DeserializeObject<T>(serializedObject);
static string Serialize<T>(T objectToSerialize) => JsonConvert.SerializeObject(objectToSerialize);
Now that the list is saved in the phone, I'd like to be able to access the list and the elements inside it, as well as modify it. I'm using this block of code to accomplish it:
private List<FileResult> GetList(object instance, string path)
{
var pp = path.Split('/');
Type t = instance.GetType();
foreach( var prop in pp)
{
Console.WriteLine(prop);
PropertyInfo propInfo = t.GetProperty(prop);
Console.WriteLine(propInfo);
if (propInfo != null)
{
instance = propInfo.GetValue(instance, null);
t = instance.GetType();
}
else throw new ArgumentException("Properties path is not correct");
}
return (List<FileResult>)instance;
}
However, whatever I do, the ArgumentException gets thrown. Obviously, it's because propInfo is always null, but I don't understand why. The instance I'm giving is the list itself, and the path I'm giving is the following:
/data/user/0/com.companyname.app1/cache/2203693cc04e0be7f4f024d5f9499e13/9fe8dae02ada45a5bb9eba67d39f7d06/8907af5726ff404fadb415261a7dc71e.jpg, which is the path that I get from the following block of code (after being modified so I get only the path above):
Preferences.Get("SavedListPhoto", "false")
I've looked but I found no problems which related exactly to what I have. If someone could help me it would be greatly appreciated :)

C# VSTO word AddIn Throws value does not fall within expected error

I am new to VSTO word Addin,the end goal is to check if the custom document property exists.Read all the available articles online with no breakthrough.
Started of with this code
public void chk()
{
if (this.Application.ActiveDocument.CustomDocumentProperties["ObjectType"].Value = 0)
{
MessageBox.Show("Please select an object");
}
}
This throws the error
Value does not fall within bounds error
Modified the code to create a custom document property object as below and it gives me the same error on
if(this.Application.ActiveDocument.CustomDocumentProperties["ObjectType"].Value
= 0)
public void chk()
{
dynamic properties = null;
properties = this.Application.ActiveDocument.CustomDocumentProperties;
properties.Add("Name",false,Office.MsoDocProperties.msoPropertyTypeString, "ObjectType");
properties.Add("LinkToContent",false, Office.MsoDocProperties.msoPropertyTypeBoolean,false);
properties.Add("Type",false,Office.MsoDocProperties.msoPropertyTypeNumber, 0);
if(this.Application.ActiveDocument.CustomDocumentProperties["ObjectType"].Value = 0)
{
MessageBox.Show("Please select an object");
}
}
Requesting you to suggest the steps to fix the issue. Please let me know if more information is required.
You can iterate over all properties and check their names, compare two approaches:
void TestProperties()
{
Microsoft.Office.Core.DocumentProperties properties;
properties = (Office.DocumentProperties)this.CustomDocumentProperties;
if (ReadDocumentProperty("Project Name") != null)
{
properties["Project Name"].Delete();
}
properties.Add("Project Name", false,
Microsoft.Office.Core.MsoDocProperties.msoPropertyTypeString,
"White Papers");
}
private string ReadDocumentProperty(string propertyName)
{
Office.DocumentProperties properties;
properties = (Office.DocumentProperties)this.CustomDocumentProperties;
foreach (Office.DocumentProperty prop in properties)
{
if (prop.Name == propertyName)
{
return prop.Value.ToString();
}
}
return null;
}

How to read json file in asp.net web api

In my asp.web api 2.0 project I have a Json file, where all the error codes are mapped. I want to read the json file in order to return response to the caller.
I am unable to read the same, however if I use console application following code works, any suggestion will be helpful.
Code that works in console application:
var assembly = Assembly.GetExecutingAssembly();
using (var stream = new StreamReader(assembly.GetManifestResourceStream("ConsoleApp24.Utilities.StatusCodes.json") ?? throw new InvalidOperationException()))
{
var status = JsonConvert.DeserializeObject<RootObject>(stream.ReadToEnd());
}
Using above code provides assembly as null in web api project, hence I changed it to following:
var assembly = GetWebEntryAssembly();
using (var stream = new StreamReader(assembly.GetManifestResourceStream("PaymentAccount.Api.Resources.StatusCodes.json") ?? throw new InvalidOperationException()))
{
var status = JsonConvert.DeserializeObject<RootObject>(stream.ReadToEnd());
}
private Assembly GetWebEntryAssembly()
{
if (System.Web.HttpContext.Current == null ||
System.Web.HttpContext.Current.ApplicationInstance == null)
{
return null;
}
var type = System.Web.HttpContext.Current.ApplicationInstance.GetType();
while (type != null && type.Namespace == "ASP")
{
type = type.BaseType;
}
return type == null ? null : type.Assembly;
}
The exception I get is:
Operation is not valid due to the current state of the object.
With Server.MapPath it is easy for ASP.NET to find your files but the file still have to be inside of the application root folder, here is some official documentation on this function.
Just place file inside your root folder, and then use Server.MapPath this will allow your ASP.NET application to find your file in the Server file system.
string json = File.ReadAllText(Server.MapPath("~/files/myfile.json"));
You can try this :
public object Get()
{
string allText = System.IO.File.ReadAllText(#"c:\data.json");
object jsonObject = JsonConvert.DeserializeObject(allText);
return jsonObject;
}
this code returns json text

StackOverflow in SelectSingleNode

Hello I have function which creates/updates fields in app.exe.config file
public static void UpdateConfig(string FieldName, string FieldValue, ConfigSelector SectionName = ConfigSelector.AppSettings)
{
switch (SectionName)
{
case ConfigSelector.Execption:
{
// MessageBox.Show("gg");
var xmlDoc = new XmlDocument();
xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
if (xmlDoc.SelectSingleNode("configuration/Execption") != null)
{
if (xmlDoc.SelectSingleNode("configuration/Execption/List") != null)
{
// create new node <add key="Region" value="Canterbury" />
var nodeRegion = xmlDoc.CreateElement("add");
nodeRegion.SetAttribute("key", FieldName);
nodeRegion.SetAttribute("value", FieldValue);
xmlDoc.SelectSingleNode("configuration/Execption/List").AppendChild(nodeRegion);
}
else
{
var List = xmlDoc.CreateElement("List");
xmlDoc.SelectSingleNode("configuration/Execption").AppendChild(List);
UpdateConfig(FieldName, FieldValue, SectionName);
}
}
else
{
var List = xmlDoc.CreateElement("Execption");
xmlDoc.SelectSingleNode("configuration").AppendChild(List);
UpdateConfig(FieldName, FieldValue, SectionName);
}
xmlDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
ConfigurationManager.RefreshSection("Execption/List");
break;
}
}
}
Function works first Check if xpath configuration/Execption exist, if not exist it creates this path and recalls function again, second time check if configuration/Execption/List path exist if not creates path and recalls function again, and third time adds required fields which is fieldname and fieldvalue,
but I getting System.StackOverflowException in line:
if (xmlDoc.SelectSingleNode("configuration/Execption") != null)
Did I miss something?
You are calling UpdateConfig recursively, with the exact same arguments already passed to it
UpdateConfig(FieldName, FieldValue, SectionName);
Since the recursive call happens before the xmlDoc.Save(), it always works on the same content.
Saving before doing the recursive call should fix the issue.
You don't save the document after adding the new element, so when you are loading the file in the next iteration the new element isn't there, and xmlDoc.SelectSingleNode("configuration/Execption") != null is still false, so the code creates the element again in infinite recursion and you get StackOverflowException.
Just save the document after you change it
else
{
var List = xmlDoc.CreateElement("Execption");
xmlDoc.SelectSingleNode("configuration").AppendChild(List);
xmlDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
UpdateConfig(FieldName, FieldValue, SectionName);
}

code contracts usage with exceptions

void ReadContent(string path)
{
Contract.Requires(path!=null);
string contentofileasstring = filehelperobj.GetContent(path);
if(String.IsNullOrEmpty(contentofileasstring ))
{
throw new FileContentException(path + "No content found");
}
m_xmlobj = contentofileasstring ;
}
Is my assumption of the usage of code contracts and exceptions right in this case. Do you think it is logical to replace the exception with a code contract(or vice versa)?
code not tested.Just an example scenario
I would probably go for an implementation which looks like the following:
private void ReadContent(string path)
{
Contract.Requires<FileMissingException>(File.Exists(path));
string content = filehelperobj.GetContent(path);
m_xmlobj = content;
}
Post Edit
As it's the content you want to validate, I would put a Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); inside the filehelperobj.GetContent(string) method. Then if the content being read was null or empty, I would throw an exception. e.g.
public string GetContent(string path)
{
Contract.Requires<FileMissingException>(File.Exists(path));
Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>()));
using(var reader = new StreamReader(File.OpenRead(path)))
{
var content = reader.ReadToEnd();
if(String.IsNullOrEmpty(content))
throw new FileContentException("No content found at file: " + path);
return content;
}
}
Well assuming you had the lines the wrong way round (ie, test the path for null before trying to use it) then yes, it is a valid pre-condition and therefore should be a code contract.

Categories