Find all subfolders of the Inbox folder using EWS - c#

I have the following Inbox folder structure:
Inbox
--ABC
----ABC 2
----ABC 3
--XYZ
----XYZ 2
--123
----123 A
----123 B
----123 C
I am using Exchange Web Services and the following code to find the child folders of the Inbox folder:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.AutodiscoverUrl("MyName#MyDomain.com");
Mailbox mb = new Mailbox("MyName#MyDomain.com");
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.Inbox,
new FolderView(int.MaxValue));
foreach (Folder folder in findResults.Folders)
{
Console.WriteLine(folder.DisplayName);
}
This partly works because it returns the ABC, XYZ, and 123 folders; unfortunately, it does not return the folders inside each of those folders (ABC 2, ABC 3, XYZ 2, 123 A, 123 B, 123 C).
Also, it is possible that a folder could have more than one level of subfolders inside it.
How can I write this code so that it will return all subfolders regardless of how deeply nested they may be?

You can tell EWS to do a deep traversal when searching the folders. You can do this using the FolderView.Traversal property. Your code would then be changed to something similar to the following:
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.Inbox,
new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep });

You can page your requests and get the entire folder hierarchy from the server in just a few calls. The key is the FolderView.Traversal property, as Jacob indicates.
For example, for an Exchange mailbox with ~1,300 folders the code below only makes 2 requests. You can set your page size to whatever you like, as long as you stay at or below the server limit.
FYI: Exchange Online (Office365) caps at a maximum of 1,000 items in a response. I haven't tested, so I can't speak for any similar limits when querying an on-premises Exchange Server.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security;
using Exchange = Microsoft.Exchange.WebServices.Data; // from nuget package "Microsoft.Exchange.WebServices"
namespace FolderViewTraversal
{
class Program
{
public static void Main()
{
Exchange.ExchangeService oService;
Dictionary<string, User> oUsers;
oUsers = new Dictionary<string, User>
{
{ "User1", new User("write.to.me1#my.address.com", "Some-Fancy-Password1") },
{ "User2", new User("write.to.me2#my.address.com", "Some-Fancy-Password2") }
};
foreach (KeyValuePair<string, User> Credential in oUsers)
{
File.Delete(String.Format(LOG_FILE_PATH, Credential.Key));
}
foreach (KeyValuePair<string, User> Credential in oUsers)
{
LogFileName = Credential.Key;
Console.WriteLine("Getting message counts for mailbox [{0}]...", LogFileName);
Console.WriteLine();
oService = Service.ConnectToService(Credential.Value);
GetAllFolders(oService, String.Format(LOG_FILE_PATH, Credential.Key));
Console.Clear();
};
Console.WriteLine();
Console.Write("Press any key to exit...");
Console.ReadKey();
}
private static void GetAllFolders(Exchange.ExchangeService Service, string LogFilePath)
{
Exchange.ExtendedPropertyDefinition oIsHidden = default;
List<Exchange.Folder> oFolders = default;
Exchange.FindFoldersResults oResults = default;
bool lHasMore = false;
Exchange.Folder oChild = default;
Exchange.FolderView oView = default;
short nPageSize = 0;
short nOffSet = 0;
List<string> oPaths = default;
List<string> oPath = default;
oIsHidden = new Exchange.ExtendedPropertyDefinition(0x10f4, Exchange.MapiPropertyType.Boolean);
nPageSize = 1000;
oFolders = new List<Exchange.Folder>();
lHasMore = true;
nOffSet = 0;
while (lHasMore)
{
oView = new Exchange.FolderView(nPageSize, nOffSet, Exchange.OffsetBasePoint.Beginning)
{
PropertySet = new Exchange.PropertySet(Exchange.BasePropertySet.IdOnly)
};
oView.PropertySet.Add(oIsHidden);
oView.PropertySet.Add(Exchange.FolderSchema.ParentFolderId);
oView.PropertySet.Add(Exchange.FolderSchema.DisplayName);
oView.PropertySet.Add(Exchange.FolderSchema.FolderClass);
oView.PropertySet.Add(Exchange.FolderSchema.TotalCount);
oView.Traversal = Exchange.FolderTraversal.Deep;
oResults = Service.FindFolders(Exchange.WellKnownFolderName.MsgFolderRoot, oView);
oFolders.AddRange(oResults.Folders);
lHasMore = oResults.MoreAvailable;
if (lHasMore)
{
nOffSet += nPageSize;
}
}
oFolders.RemoveAll(Folder => (bool)Folder.ExtendedProperties[0].Value == true);
oFolders.RemoveAll(Folder => Folder.FolderClass != "IPF.Note");
oPaths = new List<string>();
oFolders.ForEach(Folder =>
{
oChild = Folder;
oPath = new List<string>();
do
{
oPath.Add(oChild.DisplayName);
oChild = oFolders.SingleOrDefault(Parent => Parent.Id.UniqueId == oChild.ParentFolderId.UniqueId);
} while (oChild != null);
oPath.Reverse();
oPaths.Add(String.Format("{0}{1}{2}", String.Join(DELIMITER, oPath), '\t', Folder.TotalCount));
});
oPaths.RemoveAll(Path => Path.StartsWith("Sync Issues"));
File.WriteAllText(LogFilePath, String.Join(Environment.NewLine, oPaths));
}
private static string LogFileName;
private const string LOG_FILE_PATH = "D:\\Emails\\Remote{0}.txt";
private const string DELIMITER = "\\";
}
internal class Service
{
public static Exchange.ExchangeService ConnectToService(User User)
{
return Service.ConnectToService(User, null);
}
public static Exchange.ExchangeService ConnectToService(User User, Exchange.ITraceListener Listener)
{
Exchange.ExchangeService oService = default;
oService = new Exchange.ExchangeService(Exchange.ExchangeVersion.Exchange2013_SP1)
{
Credentials = new NetworkCredential(User.EmailAddress, User.Password)
};
oService.AutodiscoverUrl(User.EmailAddress, RedirectionUrlValidationCallback);
if (Listener != null)
{
oService.TraceListener = Listener;
oService.TraceEnabled = true;
oService.TraceFlags = Exchange.TraceFlags.All;
}
return oService;
}
private static bool RedirectionUrlValidationCallback(string RedirectionUrl)
{
var _with1 = new Uri(RedirectionUrl);
return _with1.Scheme.ToLower() == "https";
}
}
internal class User
{
public string EmailAddress { get; }
public SecureString Password { get; }
public User(string EmailAddress)
{
this.EmailAddress = EmailAddress;
this.Password = new SecureString();
}
public User(string EmailAddress, string Password)
{
this.EmailAddress = EmailAddress;
this.Password = new SecureString();
foreach(char Chr in Password) { this.Password.AppendChar(Chr); };
this.Password.MakeReadOnly();
}
public static User GetUser()
{
Console.Write("Enter email address: ");
string sEmailAddress = Console.ReadLine();
Console.Write("Enter password: ");
User functionReturnValue = new User(sEmailAddress);
while (true)
{
ConsoleKeyInfo oUserInput = Console.ReadKey(true);
if (oUserInput.Key == ConsoleKey.Enter)
{
break; // TODO: might not be correct. Was : Exit While
}
else if (oUserInput.Key == ConsoleKey.Escape)
{
functionReturnValue.Password.Clear();
}
else if (oUserInput.Key == ConsoleKey.Backspace)
{
if (functionReturnValue.Password.Length != 0)
{
functionReturnValue.Password.RemoveAt(functionReturnValue.Password.Length - 1);
}
}
else
{
functionReturnValue.Password.AppendChar(oUserInput.KeyChar);
Console.Write("*");
}
}
if (functionReturnValue.Password.Length == 0)
{
functionReturnValue = null;
}
else
{
functionReturnValue.Password.MakeReadOnly();
Console.WriteLine();
}
return functionReturnValue;
}
}
internal class TraceListener : Exchange.ITraceListener
{
public void Trace(string TraceType, string TraceMessage)
{
File.AppendAllText(String.Format("{0}.txt", Path.Combine("D:\\Emails\\TraceOutput", Guid.NewGuid().ToString("D"))), TraceMessage);
}
}
}

Related

RAVENDB The name "Store" doesn't exist in the current context

I've been working on getting this to work all day, and haven't had any success. I want to clean up my code and separate different chunks of code into different classes and functions. Here is a chunk of code that refuses to run.
using System;
using Raven.Client.Documents;
namespace RavendbTest
{
class Program
{
static void Main(string[] args)
{
var store = new DocumentStore
{
Urls = new[] { "http://localhost:8080" },
Database = "Tasks"
};
store.Initialize();
}
static void Checking()
{
Console.WriteLine("Login or Sign Up? (L/S)");
string userInput = Console.ReadLine();
if (userInput.ToLower() == "l")
{
Console.WriteLine("Logging you in");
}
else if (userInput.ToLower() == "s")
{
Console.WriteLine("Signing you up\n");
Console.Write("First Name: ");
string firstName = Console.ReadLine();
char firstNameInitial = firstName.ToLower()[0];
Console.WriteLine(firstNameInitial);
Console.Write("Last Name: ");
string lastName = Console.ReadLine();
char lastNameInitial = lastName.ToLower()[0];
Console.WriteLine(lastNameInitial);
Console.Write("Email: ");
string email = Console.ReadLine();
string combinedInitial = firstNameInitial.ToString() + lastNameInitial.ToString();
Console.WriteLine(combinedInitial);
// Checking if email has a '#' symbol in it. Determine validity
bool isVerified = false;
for (int i = 0; email.Length > i; i++)
{
if (email[i] != '#')
{
continue;
}
else if (email[i] == '#')
{
isVerified = true;
}
}
if (isVerified == true)
{
using (var session = Store.OpenSession())
{
var task = session.Load<Entity>(combinedInitial + email);
if (task == null)
{
Console.WriteLine("Creating your account");
var newUser = new Entity
{
Id = combinedInitial + email,
FirstName = firstName,
LastName = lastName,
Email = email
};
session.Store(newUser);
session.SaveChanges();
}
else
{
Console.WriteLine("This email is already in use... Would you like to login? (Y/N)");
string changeChoice = Console.ReadLine();
if (changeChoice.ToLower()[0] == 'y')
{
}
else
{
Console.WriteLine("Exiting Program");
}
}
using (var session = store.OpenSession())
{
var task = session.Load<Entity>(combinedInitial + email);
}
}
}
else
{
Console.WriteLine("Please enter a valid email address");
Console.WriteLine("Exiting Program");
}
}
else
{
Console.WriteLine("Error");
}
}
}
}
I thinking that I'm getting errors because my function checking can't see that I've already initialize a DocumentStore. Any help is greatly appreciated

WebRequests in C# are very CPU Intensive. Need something better

I have a program that needs to scan for other devices running my program on the network. The solution I came up with was to call each ipAddress to see if my program is running.
The code below is completely blocking the cpu:-
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FileWire
{
class SearchNearby
{
private bool pc_search_cancelled = false;
private SynchronizedCollection<Thread> PCSearchThreadList;
private ConcurrentDictionary<String, String> NearbyPCList;
public void NewPcFound(string s, string s1)
{
Console.WriteLine(string.Format("PC Found at: {0} PC Name: {1}", s, s1));
}
public SearchNearby()
{
startPCScan();
while (true)
{
bool isAnyAlive = false;
foreach(Thread t in PCSearchThreadList)
{
isAnyAlive |= t.IsAlive;
}
if (!isAnyAlive)
{
Console.WriteLine("Search Complete");
foreach (var a in NearbyPCList)
{
Console.WriteLine(a.Key + " ;; " + a.Value);
}
startPCScan();
}
Thread.Sleep(100);
}
}
private void startPCScan()
{
PCSearchThreadList = new SynchronizedCollection<Thread>();
NearbyPCList = new ConcurrentDictionary<String, String>();
pc_search_cancelled = false;
String add = "";
System.Net.IPAddress[] ad = System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList;
foreach (System.Net.IPAddress ip in ad)
{
add += ip.ToString() + "\n";
}
bool connected;
if (add.Trim(' ').Length == 0)
{
connected = false;
}
else
{
connected = true;
}
if (connected)
{
try
{
String[] addresses = add.Split('\n');
foreach (String address in addresses)
{
int myIP = int.Parse(address.Substring(address.LastIndexOf(".") + 1));
for (int def = 0; def <= 10; def++)
{
int finalDef = def;
for (int j = 0; j < 10; j++)
{
string finalJ = j.ToString();
Thread thread = new Thread(new ThreadStart(() =>
{
if (!pc_search_cancelled)
{
for (int i = (finalDef * 25); i < (finalDef * 25) + 25 && i <= 255; i++)
{
if (!pc_search_cancelled)
{
if (i != myIP)
{
String callToAddress = "http://" + address.Substring(0, address.LastIndexOf(".")) + "." + i + ":" + (1234 + int.Parse(finalJ)).ToString();
String name = canGetNameAndAvatar(callToAddress);
if (name != null)
{
NearbyPCList[callToAddress] = name;
NewPcFound(callToAddress, name);
}
}
}
}
}
}));
PCSearchThreadList.Add(thread);
thread.Start();
}
}
}
} catch (Exception e) {
}
}
}
private String canGetNameAndAvatar(String connection)
{
String link = connection + "/getAvatarAndName";
link = link.Replace(" ", "%20");
try
{
var client = new HttpClient();
client.Timeout = TimeSpan.FromMilliseconds(500);
var a = new Task<HttpResponseMessage>[1];
a[0] = client.GetAsync(link);
Task.WaitAll(a);
var b = a[0].Result.Content.ReadAsStringAsync();
Task.WaitAll(b);
Console.WriteLine(b.Result);
string result = b.Result;
result = result.Substring(result.IndexOf("<body>") + 6, result.IndexOf("</body>") - (result.IndexOf("<body>") + 6));
AvtarAndName json = JsonConvert.DeserializeObject<AvtarAndName>(result);
if (json != null)
{
return json.name;
}
}
catch
{
return null;
}
return null;
}
}
}
This is the exact C# version of the java code I was using in Java:-
import com.sun.istack.internal.Nullable;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class PCScan {
private static boolean pc_search_cancelled = false;
private static List<Thread> PCSearchThreadList;
private static HashMapWithListener<String, String> NearbyPCList;
public static void main(String[] args) {
start();
while (true) {
int numCompleted = 0;
for (Thread t : PCSearchThreadList) {
if (!t.isAlive()) {
numCompleted++;
}
}
if (numCompleted == PCSearchThreadList.size()) {
start();
}
}
}
private static void start() {
try {
startPCScan();
} catch (SocketException e) {
e.printStackTrace();
}
NearbyPCList.setPutListener(new HashMapWithListener.putListener() {
#Override
public void onPut(Object key, Object value) {
System.out.println(key.toString() + ";;" + value.toString());
}
});
}
private static void startPCScan() throws SocketException {
pc_search_cancelled = false;
PCSearchThreadList = new CopyOnWriteArrayList<>();
NearbyPCList = new HashMapWithListener<>();
Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
boolean connected;
String add = "";
while (enumeration.hasMoreElements()) {
NetworkInterface interfacea = enumeration.nextElement();
if (!interfacea.isLoopback()) {
Enumeration<InetAddress> enumeration1 = interfacea.getInetAddresses();
while (enumeration1.hasMoreElements()) {
String address = enumeration1.nextElement().getHostAddress();
if (address.split("\\.").length == 4) {
add += address + "\n";
}
}
}
}
System.out.println(add);
connected = true;
if (connected) {
try {
String[] addresses = add.split("\n");
addresses = new HashSet<String>(Arrays.asList(addresses)).toArray(new String[0]);
for (String address : addresses) {
int myIP = Integer.parseInt(address.substring(address.lastIndexOf(".") + 1));
for (int def = 0; def <= 10; def++) {
int finalDef = def;
for (int j = 0; j < 10; j++) {
int finalJ = j;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
if (!pc_search_cancelled) {
for (int i = (finalDef * 25); i < (finalDef * 25) + 25 && i <= 255; i++) {
if (!pc_search_cancelled) {
if (i != myIP) {
String callToAddress = "http://" + address.substring(0, address.lastIndexOf(".")) + "." + i + ":" + String.valueOf(Integer.parseInt("1234") + finalJ);
String name = canGetNameAndAvatar(callToAddress);
if (name != null) {
NearbyPCList.put(callToAddress, name);
}
}
}
}
}
}
});
PCSearchThreadList.add(thread);
thread.start();
}
}
// }
// }).start();
}
} catch (Exception e) {
}
}
}
private static String canGetNameAndAvatar(String connection) {
String link = connection + "/getAvatarAndName";
link = link.replaceAll(" ", "%20");
try {
HttpClient client = new DefaultHttpClient();
HttpParams httpParams = client.getParams();
httpParams.setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, 500);
HttpGet request = new HttpGet();
request.setURI(new URI(link));
HttpResponse response = client.execute(request);
BufferedReader in = new BufferedReader(new
InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line="";
while ((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
String result = sb.toString();
result = result.substring(result.indexOf("<body>") + 6, result.indexOf("</body>"));
JSONObject json = new JSONObject(result);
if (json != null) {
return json.getString("name");
}
}
catch (Exception ignored){
return null;
}
return null;
}
static class HashMapWithListener<K, V> extends HashMap<K, V> {
private putListener PutListener;
public void setPutListener(putListener PutListener) {
this.PutListener = PutListener;
}
#Nullable
#Override
public V put(K key, V value) {
PutListener.onPut(key, value);
return super.put(key, value);
}
interface putListener {
public void onPut(Object key, Object value);
}
}
}
The java code runs absolutely fine and only uses about 20 percent cpu while c# code absolutely locks the PC. I tried Webclient, webrequest, httpClient. All have literally the same performance.
I need the code to be in c# as I can't include whole JRE in my program since it is too large. The rest of my program and GUI is in WPF format.
Also, I need the code to take a maximum of 50seconds while scanning ports 1234-1243. This code also works absolutely fine even on a midrange android phone. So, I don't know what the problem is.
I would suggest something like this (I've simplified it for the sake of an example):
private static HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromMilliseconds(500) };
private async Task<Something> GetSomething(string url)
{
using (HttpResponseMessage response = await _client.GetAsync(url))
{
string json = await response.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Something>(json);
}
}
private async Task<Something[]> GetSomethings(string[] urls)
{
IEnumerable<Task<Something>> requestTasks = urls.Select(u => GetSomething(u));
Something[] results = await Task.WhenAll<Something>(requestTasks);
return results;
}
You should also make the method calling GetSomethings async, and await it, and do the same all the way up the call chain.
async/await uses a thread pool to execute, and the thread is actually suspended while the IO part of the request occurs, meaning that no CPU time is used during this period. When then IO part is done, it resumes the code at the await.
Related information:
Asynchronous programming documentation
How and when to use 'async' and 'await'
You are using threads and multithreading completely wrong.
Because I cannot really understand what you are trying to do because everything is cramped into one function, I cannot provide you with a more detailed solution.
But let me suggest the following: I understand, you want to execute some operation in the background connecting to some other computer, try something like this
var taskList = new List<Task>();
foreach (var pc in computers)
{
var currentPcTask = Task.Run(() => DoYourWorkForSomePcHere(pc));
taskList.Add(currentPcTask);
}
Task.WaitAll(taskList.ToArray());
This will be very CPU efficient.

Reading from CSV file with CsvHelper

I managed to write contents from a List to a CSV file. Now I'm trying to read from the created CSV file and show the content in a Console Application. I'm getting a exception which lead me to some possible solutions on the internet. None of them are working for my Console Application. I hope you can help me.
My code from Program.cs which calls the method in FileOperations.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CsvHelper;
namespace GimpiesConsoleOOcsvListUI
{
class Program
{
static void Main(string[] args)
{
// First line to skip a row and position all users correctly under the right headers
User user0 = new User("", "", "", "");
// Create user default instances
User user1 = new User("Beheer", "beheer#gimpies.nl", "123", "admin");
User user2 = new User("Inkoop", "inkoop#gimpies.nl", "123", "purchase");
User user3 = new User("Verkoop", "verkoop#gimpies.nl", "123", "sales");
// List of default users (with a list you can add, get and remove items in the list)
List<User> users = new List<User>();
users.Add(user0);
users.Add(user1);
users.Add(user2);
users.Add(user3);
// Create login instance
LoginManager loginMgr = new LoginManager();
// Create stock instance
Stock stock = new Stock();
// Create UserList instance
UserList usrlst = new UserList();
// Call method in UserList.cs
usrlst.Users(users);
Start:
// Welcome message
Console.WriteLine("Welcome to the Gimpies Console Application! Choose 1 to login or 2 to register as guest:");
// Get input from user
string input = Console.ReadLine();
bool successfull = false;
while (!successfull)
{
if(input == "1")
{
Console.WriteLine("Enter your username:");
string username = Console.ReadLine();
Console.WriteLine("Enter your password:");
string password = Console.ReadLine();
foreach (User user in users)
{
if (username == user.UserName && password == user.PassWord && user.UserRole == "admin")
{
// Create Admin instance to be able to call methods in that class
Admin am = new Admin();
// Calling the method in Admin.cs to start Menu logic
am.AdminLoggedIn();
successfull = true;
break;
}
if (username == user.UserName && password == user.PassWord && user.UserRole == "purchase")
{
// Create Purchase instance to be able to call methods in that class
Purchase pc = new Purchase();
// Calling the method in Purchase.cs to start Menu logic
pc.PurchaseLoggedIn();
successfull = true;
break;
}
if (username == user.UserName && password == user.PassWord && user.UserRole == "sales")
{
// Create Sales instance to be able to call methods in that class
Sales sl = new Sales();
// Calling the method in Sales.cs to start Menu logic
sl.SalesLoggedIn();
successfull = true;
break;
}
if (username == user.UserName && password == user.PassWord && user.UserRole == "guest")
{
// Create Guest instance to be able to call methods in that class
Guest gt = new Guest();
// Calling the method in Guest.cs to start Menu logic
gt.GuestLoggedIn();
successfull = true;
break;
}
}
if (!successfull)
{
Console.WriteLine("Your username or password is incorrect, try again !!!");
}
}
else if (input == "2")
{
// Create instance to go to method in class RegisterManager.cs
RegisterManager rm = new RegisterManager();
rm.Register(users);
successfull = true;
goto Start;
}
else if (input == "3")
{
FileOperations fo = new FileOperations();
// Calling the method from FileOperations.cs to write the List here to a CSV file
fo.WriteUsersToCSV(users);
goto Start;
}
else if (input == "4")
{
FileOperations fo = new FileOperations();
// Calling the method from FileOperations.cs to write the List here to a CSV file
fo.ReadUsersFromCSV(users);
goto Start;
}
else
{
Console.WriteLine("Try again !!!");
break;
}
}
// // Loop over stored users within instances inside the list where users are added
// foreach (User user in users)
// {
// if(loginMgr.Login(user))
// {
// // Login successfull
// Console.WriteLine("Login user " + user.UserName);
// }
// else
// {
// // Not successfull
// }
// }
}
}
}
In Program.cs it's about the else if with input == "4".
Then the method ReadUsersFromCSV is called inside FileOperations.cs:
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;
using System.Linq;
using CsvHelper;
namespace GimpiesConsoleOOcsvListUI
{
// Handles CRUD within CSV files and able to save them
public class FileOperations
{
// Writes to CSV file from List
public void WriteUsersToCSV(List<User> users)
{
// using (var mem = new MemoryStream())
// using (var writer = new StreamWriter(mem))
using (var writer = new StreamWriter("users.csv"))
using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecords(users);
writer.Flush();
// var result = Encoding.UTF8.GetString(mem.ToArray());
// Console.WriteLine(result);
Console.WriteLine("Data saved to users.csv");
}
}
// Reads from CSV file and displays content from it (Work in progress...)
public void ReadUsersFromCSV(List<User> users)
{
// using (var mem = new MemoryStream())
// using (var writer = new StreamWriter(mem))
using (var reader = new StreamReader("users.csv"))
using (var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture))
{
// csvReader.Configuration.Delimiter = ";";
// csvReader.Configuration.HasHeaderRecord = true;
// csvReader.Configuration.AutoMap<User>();
// csvReader.ReaderHeader<User>();
// var records = csvReader.GetRecords<dynamic>();
// reader.Flush();
// var result = Encoding.UTF8.GetString(mem.ToArray());
csvReader.Read();
csvReader.ReadHeader();
csvReader.Configuration.HeaderValidated = null;
csvReader.Configuration.MissingFieldFound = null;
var records = csvReader.GetRecords<User>();
foreach (var record in records)
{
Console.WriteLine(records);
}
// Console.WriteLine(records);
}
}
// Writes to CSV file from List
public void SaveGimpiesToCSV(List<Gimpies> gimpies)
{
// using (var mem = new MemoryStream())
// using (var writer = new StreamWriter(mem))
using (var writer = new StreamWriter("gimpies.csv"))
using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<Gimpies>();
csvWriter.WriteHeader<Gimpies>();
csvWriter.WriteRecords(gimpies);
writer.Flush();
// var result = Encoding.UTF8.GetString(mem.ToArray());
// Console.WriteLine(result);
}
}
}
}
The exception:
Unhandled exception. CsvHelper.MissingFieldException: Field with name 'username' does not exist. You can ignore missing fields by setting MissingFieldFound to null.
at CsvHelper.Configuration.ConfigurationFunctions.MissingFieldFound(String[] headerNames, Int32 index, ReadingContext context)
at CsvHelper.CsvReader.GetFieldIndex(String[] names, Int32 index, Boolean isTryGet, Boolean isOptional)
at CsvHelper.CsvReader.GetFieldIndex(String name, Int32 index, Boolean isTryGet)
at CsvHelper.Expressions.ExpressionManager.CreateConstructorArgumentExpressionsForMapping(ClassMap map, List`1 argumentExpressions)
at CsvHelper.Expressions.ObjectRecordCreator.CreateCreateRecordDelegate(Type recordType)
at CsvHelper.Expressions.RecordCreator.GetCreateRecordDelegate(Type recordType)
at CsvHelper.Expressions.RecordCreator.Create[T]()
at CsvHelper.Expressions.RecordManager.Create[T]()
at CsvHelper.CsvReader.GetRecords[T]()+MoveNext()
at GimpiesConsoleOOcsvListUI.FileOperations.ReadUsersFromCSV(List`1 users) in /home/pascalmariany/Projects/Csharp/GimpiesConsoleOOcsvList/GimpiesConsoleOOcsvListUI/FileOperations.cs:line 55
at GimpiesConsoleOOcsvListUI.Program.Main(String[] args) in /home/pascalmariany/Projects/Csharp/GimpiesConsoleOOcsvList/GimpiesConsoleOOcsvListUI/Program.cs:line 132
The contents of the CSV file:
My User.cs:
namespace GimpiesConsoleOOcsvListUI
{
public class User
{
// Constructor
public User(string username, string email, string password, string userrole)
{
_UserName = username;
_Email = email;
_Password = password;
_UserRole = userrole;
}
private string _UserName;
private string _Email;
private string _Password;
private string _UserRole;
public string UserName
{
get { return _UserName; }
set { _UserName = value; }
}
public string Email
{
get { return _Email; }
set { _Email = value; }
}
public string PassWord
{
get { return _Password; }
set { _Password = value; }
}
public string UserRole
{
get { return _UserRole; }
set { _UserRole = value; }
}
}
}
What would I need to change?
Update:
I read all the feedback and I changed some thing in the method within FileOperations.cs:
// Reads from CSV file and displays content from it (Work in progress...)
public void ReadUsersFromCSV(List<User> users)
{
// using (var mem = new MemoryStream())
// using (var writer = new StreamWriter(mem))
using (var reader = new StreamReader("users.csv"))
using (var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture))
{
try
{
csvReader.Configuration.Delimiter = ";";
csvReader.Configuration.IgnoreBlankLines = true;
csvReader.Configuration.HasHeaderRecord = true;
csvReader.Configuration.PrepareHeaderForMatch = (string header, int index) => header.ToLower();
csvReader.Configuration.MissingFieldFound = null;
// csvReader.Configuration.AutoMap<User>();
// csvReader.ReaderHeader<User>();
// var records = csvReader.GetRecords<dynamic>();
// reader.Flush();
// var result = Encoding.UTF8.GetString(mem.ToArray());
csvReader.Read();
csvReader.ReadHeader();
// csvReader.Configuration.HeaderValidated = null;
// Store all content inside a new List as objetcs
var records = csvReader.GetRecords<User>().ToList();
// users.ForEach(Console.WriteLine);
foreach (var record in records)
{
Console.WriteLine(record);
}
}
catch (CsvHelper.HeaderValidationException exception)
{
Console.WriteLine(exception);
}
}
}
I don't get an exception now, but I get this as output:
GimpiesConsoleOOcsvListUI.User
GimpiesConsoleOOcsvListUI.User
GimpiesConsoleOOcsvListUI.User
GimpiesConsoleOOcsvListUI.User
It's the correct amount of rows, but as you can see it doesn't display the contents which is stored from the CSV file into a List as objects.
Am I missing something?
I managed to solve it. I needed to adjust the foreach loop:
public void ReadUsersFromCSV(List<User> users)
{
// using (var mem = new MemoryStream())
// using (var writer = new StreamWriter(mem))
using (var reader = new StreamReader("users.csv"))
using (var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture))
{
try
{
csvReader.Configuration.Delimiter = ";";
csvReader.Configuration.IgnoreBlankLines = true;
csvReader.Configuration.HasHeaderRecord = true;
csvReader.Configuration.PrepareHeaderForMatch = (string header, int index) => header.ToLower();
csvReader.Configuration.MissingFieldFound = null;
csvReader.Read();
csvReader.ReadHeader();
// Store all content inside a new List as objetcs
var records = csvReader.GetRecords<User>().ToList();
// Loop through the List and show them in Console
foreach (var record in records)
{
Console.WriteLine($"{record.username } {record.email} {record.password} {record.userrole}");
}
}
catch (CsvHelper.HeaderValidationException exception)
{
Console.WriteLine(exception);
}
}
}
Thanks, but the most I learned from this video: Link for Lists

How to use string from user input to complement an object in C#

So I am using InstaSharper, and I want to make the user to type in their name of target user, however, Instead of processing the data, it just does nothing at all. Here's my code:
class Program
{
//username and pass
#region Hidden
#endregion
private static UserSessionData user;
private static IInstaApi api;
static void Main(string[] args)
{
string inputUser;
string inputPass;
Console.WriteLine("Enter the username");
inputUser = Console.ReadLine();
Console.WriteLine("Enter your password:");
inputPass = Console.ReadLine();
user = new UserSessionData();
user.UserName = inputUser;
user.Password = inputPass;
Login();
Console.Read();
}
public static async void Login()
{
//login attempt
api = InstaApiBuilder.CreateBuilder()
.SetUser(user)
.UseLogger(new DebugLogger(LogLevel.Exceptions))
.Build();
var loginRequest = await api.LoginAsync();
if (loginRequest.Succeeded)
{
string targetUser;
Console.WriteLine("Logged in!\n\t");
Console.WriteLine("Now enter the target user");
targetUser = Console.ReadLine();
PullUserPosts(targetUser);
}
else
{
Console.WriteLine("Error logging in, are you sure you have entered the right credentials?");
}
}
public static async void PullUserPosts(string userToScrape)
{
//instagram show followers demo
var userinfo = await api.GetUserInfoByIdAsync(123456789);
Console.WriteLine($"USER: {userinfo.Value.FullName}\n\tFollowers: {userinfo.Value.FollowerCount} \n \t Is it verified?\n\t {userinfo.Value.IsVerified}\n\t\n\t");
Console.WriteLine("Loading all posts and captions by target user.. \n\t");
IResult<InstaMediaList> media = await api.GetUserMediaAsync(userToScrape, PaginationParameters.MaxPagesToLoad(5));
List<InstaMedia> mediaList = media.Value.ToList();
for (int i = 0; i < mediaList.Count; i++)
{
InstaMedia m = mediaList[i];
if (m != null && m.Caption != null)
{
string captionText = m.Caption.Text;
if (captionText != null)
{
if (m.MediaType == InstaMediaType.Image)
{
for (int x = 0; x < m.Images.Count; x++)
{
if (m.Images[x] != null && m.Images[x].URI != null)
{
Console.WriteLine($"\n\t{captionText}\n\t");
string uri = m.Images[x].URI;
Console.Write($"{uri}\n\t");
}
}
}
}
}
}
it manages to log in, but when I tell user to "Now enter the target user", nothing happened. Does anyone know how to fix it?

Unity C# GraphQL Post Request Body Authentication

I am working on trying to connect to my GraphQL server my developers have setup from within Unity. I have found some scripts to help with this process, however, I am still not able to connect because i need to be logged into the system hosting graphql to be able to query externally, I cannot just use the endpoint url.
My developer has told me to do a POST request to mysystem/login and in the request body add {email: string, password: string}. I have tried a few different things and nothing is working. I have to log into the mysystem/login with email and password, then i will be able to connect to mygraphql endpoint from the code below.--i was assuming this portion would go where I have the //smt authentication notes. Any help on how to setup the post request and where it should be or how it should work would be much appreciated.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using SimpleJSON;
using UnityEngine;
using UnityEngine.Networking;
namespace graphQLClient
{
public class GraphQuery : MonoBehaviour
{
public static GraphQuery instance = null;
[Tooltip("The url of the node endpoint of the graphQL server being queried")]
public static string url;
public delegate void QueryComplete();
public static event QueryComplete onQueryComplete;
public enum Status { Neutral, Loading, Complete, Error };
public static Status queryStatus;
public static string queryReturn;
string authURL;
public static string LoginToken;
public class Query
{
public string query;
}
public void Awake()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
StartCoroutine("PostLogin");
}
private void Start()
{
LoginToken = "";
}
public static Dictionary<string, string> variable = new Dictionary<string, string>();
public static Dictionary<string, string[]> array = new Dictionary<string, string[]>();
// Use this for initialization
// SMT Authentication to ELP
// SMT Needed for Authentication--- if (token != null) request.SetRequestHeader("Authorization", "Bearer " + token);
//In the request body: {email: string, password: string}
//You’ll either get a 401 with an empty response or 201 with {token: string, user: object}
IEnumerator PostLogin()
{
Debug.Log("Logging in...");
string authURL = "https://myapp.com/login";
string loginBody = "{\"email\":\"myemail.com\",\"password\":\"mypassowrd\"}";
var request = new UnityWebRequest(authURL, "POST");
byte[] bodyRaw = new System.Text.UTF8Encoding().GetBytes(loginBody);
request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
Debug.Log("Login error!");
foreach (KeyValuePair<string, string> entry in request.GetResponseHeaders())
{
Debug.Log(entry.Value + "=" + entry.Key);
}
Debug.Log(request.error);
}
else
{
Debug.Log("Login complete!");
//Debug.Log(request.downloadHandler.text);
LoginToken = request.downloadHandler.text;
Debug.Log(LoginToken);
}
}
public static WWW POST(string details)
{
//var request = new UnityWebRequest(url, "POST");
details = QuerySorter(details);
Query query = new Query();
string jsonData = "";
WWWForm form = new WWWForm();
query = new Query { query = details };
jsonData = JsonUtility.ToJson(query);
byte[] postData = Encoding.ASCII.GetBytes(jsonData);
Dictionary<string, string> postHeader = form.headers;
//postHeader["Authorization"] = "Bearer " + downloadHandler.Token;
if (postHeader.ContainsKey("Content-Type"))
//postHeader["Content-Type"] = "application/json";
postHeader.Add("Authorization", "Bearer " + LoginToken);
else
//postHeader.Add("Content-Type", "application/json");
postHeader.Add("Authorization", "Bearer " + LoginToken);
WWW www = new WWW(url, postData, postHeader);
instance.StartCoroutine(WaitForRequest(www));
queryStatus = Status.Loading;
return www;
}
static IEnumerator WaitForRequest(WWW data)
{
yield return data; // Wait until the download is done
if (data.error != null)
{
Debug.Log("There was an error sending request: " + data.error);
queryStatus = Status.Error;
}
else
{
queryReturn = data.text;
queryStatus = Status.Complete;
}
onQueryComplete();
}
public static string QuerySorter(string query)
{
string finalString;
string[] splitString;
string[] separators = { "$", "^" };
splitString = query.Split(separators, StringSplitOptions.RemoveEmptyEntries);
finalString = splitString[0];
for (int i = 1; i < splitString.Length; i++)
{
if (i % 2 == 0)
{
finalString += splitString[i];
}
else
{
if (!splitString[i].Contains("[]"))
{
finalString += variable[splitString[i]];
}
else
{
finalString += ArraySorter(splitString[i]);
}
}
}
return finalString;
}
public static string ArraySorter(string theArray)
{
string[] anArray;
string solution;
anArray = array[theArray];
solution = "[";
foreach (string a in anArray)
{
}
for (int i = 0; i < anArray.Length; i++)
{
solution += anArray[i].Trim(new Char[] { '"' });
if (i < anArray.Length - 1)
solution += ",";
}
solution += "]";
Debug.Log("This is solution " + solution);
return solution;
}
}
}

Categories