Search code examples
c#xmlvisual-studioxamarinaccess-denied

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 enter image description here

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. :)


Solution

  • 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
    }