How to do my Silverlight project read my xml file? - c#

I have a big problem. I have to do a quiz in Silverlight with different level of difficulty. I never use this framework and now I try to learn. First, I tried to read my xml file with this framework and I used c# as programming language.
I wrote this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace quiz4
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
var quizzes = new List<Quiz>();
var objSettings = new XmlReaderSettings();
objSettings.IgnoreWhitespace = true;
objSettings.IgnoreComments = true;
const string booksFile = #"D:\quiz.xml";
string element = "";
using (XmlReader objReader = XmlReader.Create(booksFile, objSettings))
{
bool isLastElement = false;
var quiz = new Quiz();
var dx = new List<Answers>();
while (objReader.Read())
{
if (objReader.NodeType == XmlNodeType.Element)
{
element = objReader.Name;
if (element == "question")
{
quiz = new Quiz();
dx = new List<Answers>();
isLastElement = true;
}
}
else if (objReader.NodeType == XmlNodeType.Text)
{
switch (element)
{
case "questionText":
quiz.QuestionText = objReader.Value;
//Console.WriteLine("questionText: " + objReader.Value);
break;
case "LEVEL":
quiz.Level = objReader.Value;
//Console.WriteLine("LEVEL " + objReader.Value);
break;
case "correct":
dx.Add(new Answers() { IsCorrect = true, AnswerName = objReader.Value });
//Console.WriteLine("correct: " + objReader.Value);
break;
case "incorrect":
dx.Add(new Answers() { IsCorrect = false, AnswerName = objReader.Value });
//Console.WriteLine("incorrect: " + objReader.Value);
break;
}
}
if (isLastElement)
{
quiz.AnswerList = dx;
quizzes.Add(quiz);
isLastElement = false;
}
}
}
}
class Quiz
{
public string QuestionText;
public string Level;
public List<Answers> AnswerList;//lista de raspunsuri
}
public class Answers
{
public bool IsCorrect;//raspuncul poate fi adevarat(true) sau false.
public string AnswerName;//raspunsul
}
XML file:
<?xml version="1.0" encoding="utf-8" ?>
<quiz>
<question>
<questionText>In Oracle SQL * PLUS, functia LOWER (col/value) permite:</questionText>
<LEVEL>2</LEVEL>
<correct>fortarea caracterelor scrise cu litere mari sau mixte, in caractere scrise cu litere mici</correct>
<incorrect>fortarea caracterelor scrise cu litere mici in caractere scrise cu litere maric)</incorrect>
<incorrect>returnarea numarului de caractere din coloana sau valoarea literalad)</incorrect>
<incorrect>translatarea lungimii caracterelor dintr-o coloana/valoare la o lungime specificata</incorrect>
</question>
<question>
<questionText>In Oracle SQL * PLUS, functia INITCAP permite:</questionText>
<LEVEL>1</LEVEL>
<incorrect>transformarea oricarei litere a unui cuvant, in litera mare</incorrect>
<correct>transformarea primei litere a fiecarui cuvant/coloana in litera mare</correct>
<incorrect>transformarea unei litere specificate a unui cuvant , intr-o litera mare </incorrect>
<incorrect>este o similitudine cu alte SGBD si nu exista specificata in SQL*PLYS</incorrect>
</question>
</quiz>
When I press F5 nothing happends. Why? Can someone help me? Thanks!

As stated in an earlier answer, you can't access files directly from the local files structure in Silverlight. The way you usally do this is to host the file (in your case the quiz.xml) on the web server and let Silverlight do a call to the web server to fetch the file. You can host the file on the same web server that is hosting the silverlight application. This is done asynchronously, and you could initiate this call in the constructor. Another thing is the way you read the xml-file, it looks a bit strange to me, I would prefer to use Linq to XML. So here is what I would do:
public partial class MainPage : UserControl
{
private List<Quiz> quizzes;
public MainPage()
{
InitializeComponent();
var xmlUri = new Uri("http://yoursite.com/quiz.xml");
var downloader = new WebClient();
downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted);
downloader.OpenReadAsync(xmlUri);
}
void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
Stream responseStream = e.Result;
using (var reader = XmlReader.Create(responseStream))
{
var doc = XDocument.Read(reader);
quizzes = doc.Descendants("question")
.Select(q => new Quiz
{
QuestionText = q.Element("questionText").Value,
Level = q.Element("LEVEL").Value,
AnswerList = q.Descendants("incorrect")
.Select(i => new Answers
{
IsCorrect = false,
AnswerName = i.Value
})
.Union(
q.Descendants("correct")
.Select(i => new Answers
{
IsCorrect = true,
AnswerName = i.Value
})).ToList()
}).ToList();
}
}
}
}

Silverlight is running in a sandbox in the browser your application does not have access to the local file system (e.g. D:\quiz.xml). You will have to install your Silverlight application as a trusted application to get full access to the local file system.
If you manage to get around this restriction in Silverlight you should make another change to your application. Right now you are reading the XML in the constructor of the MainPage class (and because of the restriction I have described an exception is thrown). You should move this code into and event handler (e.g. for the Loaded event) but you should also make sure that any file system or network access is done using asynchronous methods. E.g., the UI is updated in asynchronous callbacks.
If you are learning C# you will discover that writing a Silverlight application will move focus away from simply learning the language because of the additional restrictions imposed by Silverlight.

Related

loading loose XAML drawing securely

A C# Windows application would like to load vector drawings that are stored in loose XAML files without allowing arbitrary code execution.
I am already loading such drawings from resources in linked assemblies over which I have control. However, I would like to also support loading loose XAML files. I imagine you can use XAML access control to limit the objects that can be instantiated in such XAML? Ideally, I would limit the loader to instantiating only the drawing primitives that are in the files we know about. It's ok that it would reject a file that has new drawing primitives in it that we have not whitelisted.
Is this a standard thing already supported by an API? Because I could not find it. Otherwise, does anyone have an example or beginnings of an example? This is for a free open source project and any help getting started would probably cut down the research I need to do by a lot.
The following seems to do a pretty decent job of white listing specific types in a XAML load:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xaml;
using System.Xml;
namespace TestXamlLoading
{
internal class SchemaContext : XamlSchemaContext
{
// map from XAML element name to required namespace (currently always the same)
private static readonly Dictionary<string, string> AllowedTypes = new Dictionary<string, string>();
static SchemaContext()
{
// questionable: <Image> is used in some drawing XAML, should review it
foreach (string name in new[]
{
"Canvas", "Compound", "Ellipse", "GradientStop", "GradientStopCollection", "Group", "Line",
"LinearGradientBrush", "MatrixTransform", "Path", "PathGeometry", "Polygon",
"RadialGradientBrush", "Rectangle", "RotateTransform", "ScaleTransform", "SkewTransform", "TextBlock",
"TransformGroup", "TranslateTransform"
})
{
AllowedTypes[name] = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
}
}
public SchemaContext(IEnumerable<Assembly> referenceAssemblies, XamlSchemaContextSettings settings) : base(
referenceAssemblies, settings)
{
// no code
}
protected override XamlType GetXamlType(string xamlNamespace, string name, params XamlType[] typeArguments)
{
if (!AllowedTypes.TryGetValue(name, out string requiredNamespace) || xamlNamespace != requiredNamespace)
{
throw new Exception($"disallowed instantiation of '{xamlNamespace}' '{name}' from XAML");
}
return base.GetXamlType(xamlNamespace, name, typeArguments);
}
}
internal class Program
{
[STAThreadAttribute]
private static void Main(string[] args)
{
bool shouldFail = TestLoad("..\\..\\..\\badfile.xaml");
Debug.Assert(!shouldFail);
bool shouldSucceed = TestLoad("..\\..\\..\\goodfile.xaml");
Debug.Assert(shouldSucceed);
}
private static bool TestLoad(string path)
{
Stream inputStream = new FileStream(path, FileMode.Open);
XmlReader xmlReader = new XmlTextReader(inputStream);
Assembly[] referenceAssemblies =
{
// these are two separate assemblies which contain all the types we allow
Assembly.GetAssembly(typeof(Canvas)),
Assembly.GetAssembly(typeof(TransformGroup))
};
XamlSchemaContextSettings settings = new XamlSchemaContextSettings();
XamlSchemaContext schemaContext = new SchemaContext(referenceAssemblies, settings);
try
{
XamlReader reader = new XamlXmlReader(xmlReader, schemaContext);
Canvas canvas = (Canvas) System.Windows.Markup.XamlReader.Load(reader);
}
catch (Exception e)
{
Debug.WriteLine(e);
return false;
}
return true;
}
}
}

Get information from XML file in C# requested in dialog

I'm trying to parse/get the information of an XML file where I have saved the setting values.
I would like to open a dialog, where the user can select the .xml file and after that get the information and load the settings.
The XML file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<Configuration version="1.2" createDate="2018-07-17T10:00:00">
<AutoScale>1</Autoscale>
<Threshold>2142</Threshold>
<MinAuto>14</MinAuto>
<MinMan>1</MinMan>
<MaxMan>1</MaxMan>
<BlueBackground>1</BlueBackground>
<Contour>1</Contour>
<Rotate>180</Rotate>
<Flip>Vertical</Flip>
</Configuration>
My code (in C#) looks like this:
using (var openFileDialogXML = new OpenFileDialog()){
System.IO.Stream myStream = null;
openFileDialogXML.InitialDirectory = #System.Environment.CurrentDirectory;
openFileDialogXML.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*";
openFileDialogXML.FilterIndex = 1;
openFileDialogXML.RestoreDirectory = true;
DialogResult dr = openFileDialogXML.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
using (XmlReader reader = XmlReader.Create(openFileDialogXML.FileName))
{
reader.MoveToContent();
var version = reader.GetAttribute("version");
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "AutoScale":
//Get AutoScale value
break;
case "Threshold":
break;
case "MinAuto":
break;
case "MinMan":
break;
case "MaxMan":
break;
}
}
}
}
I'm open to use any parser but I would like to read it element by element because it could happen that we add new settings in the future.
Can you please help me/ give me some advice about how I can reach this?
I like using Xml Linq and putting results into a dictionary so when new items are added the xml parser doesn't have to change :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication53
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Element("Configuration").Elements()
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
I would suggest to use DataContract and load the XML into specified object. When your configuration file changes, you would need to update also the Entity.
[DataContract]
public class MyXmlClass
{
[DataMember]
public int PropertyToSerialize { get; set; }
}
You can then use DataContractSerializer as described here - https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/serialization-and-deserialization
It will be much easier for you to work with object than parsing XML manually :)
Some quick and dirty answer if you want to parse it manually:
using System.Xml;
[...]
XmlTextReader xtr = new XmlTextReader(GetResourceStream("config.xml"));
while (xtr.Read())
{
if (xtr.AttributeCount == 0)
continue;
if (xtr.LocalName == "Configuration")
{
string version = xtr.GetAttribute("version");
string date = xtr.GetAttribute("createDate");
Console.WriteLine($"version={version} - date = {date}")
}
else if (xtr.LocalName == "AutoScale")
{
string autoscale = xtr.ReadString();
Console.WriteLine($"autoscale={autoscale}")
}
[...]
}
xtr.Close();
I didn't try the code, if you need more start by looking XmlTextReader examples or documentation (stackoverflow should have plenty of them)

System.UnauthorizedAccessException C# Windows 10 Phone Emulator

I know there is a bunch of threads on seemingly the same issue but I cannot for the life of me figure this out after 3 hours so I really need some help.
I understand that I am getting this error because the system does not have access to the file. I have tried setting permissions to full and a few other code snippets to solve my issue but none have worked.
This is a windows 10 app using Xaramin,
I am trying to populate a listbox with contact from an XML file. I have the list box itemsSource set to "Data Context" and path "myList". The XML build action is set to "Content" and the Copy to Output Directory Set to "Copy Always".
I have attempted to follow the tutorial from my course from the beginner 3 times and always get the same error.
Here is the error I am getting
Below is the entire code on the page.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.Xml;
using System.Xml.Linq;
using Windows.Storage;
using System.Collections.ObjectModel;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace ContactsApp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
string TEMPFILEPATH = "";
string TARGETFILEPATH = "";
private ObservableCollection<string> lstd = new ObservableCollection<string>();
public ObservableCollection<string> myList { get { return lstd; } }
public MainPage()
{
this.InitializeComponent();
}
private void Grid_Loading(FrameworkElement sender, object args)
{
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
StorageFolder installedLocation = package.InstalledLocation;
StorageFolder targetLocation = ApplicationData.Current.LocalFolder;
TEMPFILEPATH = installedLocation.Path.ToString() + "\\Contacts.xml";
TARGETFILEPATH = targetLocation.Path.ToString() + "\\Contacts.xml";
File.Move(TEMPFILEPATH, TARGETFILEPATH);
loadContacts();
}
private void loadContacts()
{
XmlReader xmlReader = XmlReader.Create(TARGETFILEPATH);
while (xmlReader.Read())
{
if (xmlReader.Name.Equals("ID") && (xmlReader.NodeType == XmlNodeType.Element))
{
lstd.Add(xmlReader.ReadElementContentAsString());
}
}
DataContext = this;
xmlReader.Dispose();
}
}
}
I will be eternally grateful for any help regarding the matter. :)
You should not try to access restricted paths in constrained environments (like Windows Phone).
Instead, if you really need to embed this file with your application, change the build action to Embedded Resource and to Do not copy for your xml file, and then retrieve the resource inside your code as an Embedded Resource:
public void LoadContacts()
{
const string fileName = "Contacts.xml";
var assembly = typeof(MainPage).GetTypeInfo().Assembly;
var path = assembly.GetManifestResourceNames()
.FirstOrDefault(n => n.EndsWith(fileName, StringComparison.OrdinalIgnoreCase));
if(path == null)
throw new Exception("File not found");
using (var stream = assembly.GetManifestResourceStream(path))
using (var reader = XmlReader.Create(stream))
{
while (reader.Read())
{
if (reader.Name.Equals("ID") && (reader.NodeType == XmlNodeType.Element))
{
lstd.Add(reader.ReadElementContentAsString());
}
}
}
DataContext = this; // better to move this inside the constructor
}

C# cannot connect to vmware

I have a project where i will have to build dual stacked virtual machines. I usually work with powershell but it does not appear to be able to do that. I may have to use C#. I am kinda rusty on this but for some reason this code give me an error "Cannot create an instance of the abstract class or interface 'VMware.Vim.VimClient'".
using System.Text;
using VMware.Vim;
namespace Vimfunctions
{
public class VimFunctions
{
protected VimClient ConnectServer(string viServer, string viUser, string viPassword)
{
**VimClient vClient = new VimClient();**
ServiceContent vimServiceContent = new ServiceContent();
UserSession vimSession = new UserSession();
vClient.Connect("https://" + viServer.Trim() + "/sdk");
vimSession = vClient.Login(viUser, viPassword);
vimServiceContent = vClient.ServiceContent;
return vClient;
}
I added the reference to the project. I must have forgot to do something.
As per https://communities.vmware.com/thread/478700:
"either stick with the PowerCLI 5.5 release as mentioned or to modify your code to use the VimClientImpl class instead of VimClient (which is now an interface)."
A complete simple example I used:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VMware.Vim;
namespace vSphereCli
{
class Program
{
static void Main(string[] args)
{
VMware.Vim.VimClientImpl c = new VimClientImpl();
ServiceContent sc = c.Connect("https://HOSTNAME/sdk");
UserSession us = c.Login("admin#vsphere.local", "password");
IList<VMware.Vim.EntityViewBase> vms = c.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, null, null);
foreach (VMware.Vim.EntityViewBase tmp in vms)
{
VMware.Vim.VirtualMachine vm = (VMware.Vim.VirtualMachine)tmp;
Console.WriteLine((bool)(vm.Guest.GuestState.Equals("running") ? true : false));
Console.WriteLine(vm.Guest.HostName != null ? (string)vm.Guest.HostName : "");
Console.WriteLine("");
}
Console.ReadLine();
}
}
}
Add a reference to "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll". Update the hostname, password; and volia!

winform Close self plus another WebBrowserControl

i know i could search proccessId / name of running tasks and kill processes i need .
though till now i was not developing schedualed tasks / self executble Applications,
so i didn't need to know how to make the application close itself after execition
trying to close everything (including WebDriver) via Application.Exit + OR this.Close()
right after i have got what i was looking for. mission Complete .
please close ... no more work for you .
but mr . Program.cs still needs somthing from Form1.
saying somthing about
Cannot access a disposed object.
Object name: 'Form1'.
any combination of both was returning in some point an exeption error
(from program.cs ) even though mission complete . no more code was requested .(?) by me..atleast.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using System.IO;
namespace HT_R_WbBrows2
{
public partial class Form1 : Form
{
public IeEnginGenerator Iengn = new IeEnginGenerator();
public Form1()
{
InitializeComponent();
//setLogView(View.Details);
string extractededVal = Iengn.ExtractPageValue(Iengn.itrfWebEng);
string flnm = #" the directory path to file --> \dolarRate.asp";
File.WriteAllText(fn, extractededVal);
this.Close();
Application.Exit();
}
public class IeEnginGenerator
{
private string directory = Environment.CurrentDirectory;///Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
public IWebDriver IwebEngine;
public List<string> ListElementsInnerHtml = new List<string>();
public HtmlAgilityPack.HtmlDocument Dnetdoc = new HtmlAgilityPack.HtmlDocument();
#region <<=========== setupDriver ============>>
public string ExtractPageValue(IWebDriver DDriver, string url="")
{
if(string.IsNullOrEmpty(url))
url = #"http://www.boi.org.il/he/Markets/ExchangeRates/Pages/Default.aspx";
var service = InternetExplorerDriverService.CreateDefaultService(directory);
service.LogFile = directory + #"\seleniumlog.txt";
service.LoggingLevel = InternetExplorerDriverLogLevel.Trace;
var options = new InternetExplorerOptions();
options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
DDriver = new InternetExplorerDriver(service, options, TimeSpan.FromSeconds(60));
DDriver.Navigate().GoToUrl(url);
Dnetdoc.LoadHtml(DDriver.PageSource);
string Target = Dnetdoc.DocumentNode.SelectNodes("//table//tr")[1].ChildNodes[7].InnerText;
//.Select(tr => tr.Elements("td").Select(td => td.InnerText).ToList())
//.ToList();
return Math.Round(Convert.ToDouble(Target), 2).ToString();
//return "";//Math.Round(Convert.ToDouble( TempTxt.Split(' ')[10]),2).ToString();
}
#endregion
}
}
}
Why use a winform application? A Console application would probably suffice for what you are doing. Once Main() ends your app will close as well. Main() never ends in a winform app because of the applications runloop.
Edit:
Here would be the correct way to do this. You need to register to the forms Load event and run your code there, not in the constructor. You can't close a winform from inside a constructor.
Edit 2: Put this code in the Form1() constructor. Somewhere after InitializeComponent();
this.Load += (sender,args)=>{ /*do all your work here*/
string extractededVal = Iengn.ExtractPageValue(Iengn.itrfWebEng);
string flnm = #" the directory path to file --> \dolarRate.asp";
File.WriteAllText(fn, extractededVal);
Application.Exit();
};

Categories