10101010101001

0101010101001

Archive for the ‘Silverlight’ Category

Unable to determine the URL to the Xap file from web

leave a comment »

I encountered today this undocumented error: “Unable to determine the URL to the Xap file from web XXX”, after renaming one of my silverlight 4 projects, which was set to run Out of Browser.
Supposing you renamed your project from XXX to YYY.
To fix the error above, go to your YYY.csproj.user on the disk, and open it for editing with notepad.
Then change

<OutOfBrowserProjectToDebug>XXX</OutOfBrowserProjectToDebug>
to 
<OutOfBrowserProjectToDebug>YYY</OutOfBrowserProjectToDebug>

Now save it, and you’re good to go.

Usually *.csproj.user files should not be under source control.
So if you rename a silverlight project which a colleague of yours has set it to be ran out of browser on his computer, then he will get this error unless you share the same *.csproj.user on the source control (which is not a good idea).

I think a visual studio 2010 improvement is needed here, that describes the situation better. Something like: “Unable to determine the URL to the Xap file from web XXX. If the project was renamed, please rename it inside your *.csproj.user” file settings as well”

Advertisements

Written by Liviu Trifoi

June 1, 2011 at 8:48 am

Silverlight IsolatedStorageFile.IncreaseQuotaTo

leave a comment »

I had a lot of troubles using IsolatedStorageFile.IncreaseQuotaTo

Msdn documentation for IsolatedStorageFile.IncreaseQuotaTo states that:
To increase the quota, you must call this method from a user-initiated event, such as in an event handler for a button-click event. When you call the IncreaseQuotaTo method, the common language runtime in Silverlight presents a dialog box for the user to approve the request. If the user declines the request, this method returns false and the quota remains the same size.

Now that seems like half-baked documentation to me since it doesn’t accurately describe what a user-initiated event is, it only gives one example.
After much digging, I did find out what a user initiated event is. Seems that the msdn documentation specifies what a user initiated event in the section related to “events overview“, but there’s no link between documentation of IsolatedStorageFile.IncreaseQuotaTo and Events Overview.
So here goes the definition:

Silverlight user-initiated events include the mouse events (such as MouseLeftButtonDown), and the keyboard events (such as KeyDown). Events of controls that are based on such events (such as Click) are also considered user-initiated.

API calls that require user initiation should be called as soon as possible in an event handler. This is because the Silverlight user initiation concept also requires that the calls occur within a certain time window after the event occurrence. In Silverlight 4, this time window is approximately one second.

User-initiated event restrictions also apply to usages of JavaScript API for Silverlight.

When Silverlight is in full-screen mode, some input events are deliberately limited for security reasons, although this can be mitigated for out-of-browser applications using elevated trust. For more information, see Full-Screen Support.

At first these limitations seemed draconian to me.
Thinking it more about it, I guess Microsoft didn’t want a user to have many tabs open in a browser and then poof: I call automatically IncreaseQuotaTo.
Since the IncreaseQuotaTo is a modal dialog, meaning you can’t navigate to other tabs from it, if the user is now on page google.com, and I show automatically IncreaseQuotaTo, the user might think that google.com is asking for more storage :)). This would be a security breach indeed.

Had they implemented this with a page level dialog, then that would have probably been more easily hacked (worked around). I can already start imagining drawing some evil forged “Silverlight needs to be updated” image over the IncreaseQuotaTo text, hence tricking the user in pressing Yes . Or maybe some other evil scenario.

I was curios though how exactly does silverlight know what a user initiated event is, but after digging through .net framework source code I’ve got to a dead end:

if ((browserService == null) || !browserService.InPrivateMode())
{
    //..
}
return false; //means that IncreaseQuota will fail
where browser.IsInPrivateMode is:

[SecuritySafeCritical]
public bool InPrivateMode()
{
    bool privateMode = false;
    return (NativeMethods.SUCCEEDED(UnsafeNativeMethods.DOM_InPrivateMode(this._browserServiceHandle, out privateMode)) && privateMode);
}

where DOM_InPrivateMode is in a DllImport[“agcore”], which according to microsoft is confidential :(
So it looks like I won’t find out soon how they’re detecting user initiated events, although I’m guessing they have some centralized private method that detects clicks for example, and then probably sets a flag that this was indeed “a user initiated event”, and since you can’t forge clicks or keypresses using javascript and since you can’t call those private methods using reflection, it’s “safe”.

Written by Liviu Trifoi

May 18, 2011 at 6:33 pm

Posted in .NET, C#, Silverlight

Tagged with , , ,

Comparing object properties in C#

leave a comment »

I needed today, in my unit tests, a way to compare two objects of the same type, property by property.
In addition to this I needed the following:

    -If the property is a reference type, then go inside it and compare that too, property by property. (Basically deep object property comparison).
    -If the property is IEnumerable, then compare properties of each element inside the IEnumerable.
    -If the elements inside the IEnumerable are themselves IEnumerable then this could go on many levels deep, but this was not on my requirements.
    -I also want the possibility to ignore certain properties in the comparison, such as property which is a delegate (like the Filter property of the PagedCollectionView framework class).
    And of course I would need to know which properties were not equal, so I could show into my assertions.

Obviously this involves some heavy reflection code which I’m sure it would be fun to write if you had the time.
An alternative is to use a free library, with just one class, that does exactly this: http://comparenetobjects.codeplex.com/
Usage is very simple, and supports all kind of useful features which you can see below:

var compareObjects = new CompareObjects()
            {
                CompareChildren = true, //this turns deep compare one, otherwise it's shallow
                CompareFields = false,
                CompareReadOnly = true,
                ComparePrivateFields = false,
                ComparePrivateProperties = false,
                CompareProperties = true,
                MaxDifferences = 1,
                ElementsToIgnore = new List<string>() { "Filter" }
            };
                                                                            
            bool areEqual = compareObjects.Compare(objectA, objectB);
            Assert.IsTrue(areEqual, compareObjects.DifferencesString); //DifferencesString contains exactly what property and what value(s) was different

For Silverlight you do have to remove a couple of line of codes from it, related to DataTable comparison, which don’t exist in silverlight, but it’s easy and only takes a couple of minutes.

Happy Deep Object Comparisons :)

Written by Liviu Trifoi

April 28, 2011 at 6:20 pm

Silverlight stack trace line numbers

with 8 comments

As you probably know, to have stack traces line numbers in a .net app you need pdb files.
In Silverlight though, pdb files don’t get included in the XAP. Even if it was possible to include them you probably wouldn’t want them there because they tend to be huge and you want to have a fast loading web-site.

So what will you do when your client calls you and says he received an error message like the one below?
NullReferenceException
at ChaptersView.ChaptersTree_OnMouseMove
at ChaptersView.GetPreviousCommandButton

After I had a look today at the answer to this question, it became obvious:

Step 1)
In the place you now log or show exceptions to the user, you stop writing a normal stack trace using exception.ToString() or exception.StackTrace.
You should write a stacktrace that includes IL offsets using the code below:

...
catch (Exception exception)
{
            string errorDescription = string.Empty;
            try
            {
                StackTrace st = new System.Diagnostics.StackTrace(ex);
                string stackTrace = "";

                if (st != null)
                {
                    foreach (StackFrame frame in st.GetFrames())
                    {
                        stackTrace = "at " + frame.GetMethod().Module.Name + "." + frame.GetMethod().ReflectedType.Name +
                                     "." + frame.GetMethod().Name + "  (IL offset: 0x" +
                                     frame.GetILOffset().ToString("x") + ")\n" + stackTrace;
                    }
                }
                errorDescription = stackTrace;
            } catch //sometimes there are no stackframes, just use ex.ToString() in those cases
            {
                errorDescription = ex.ToString();
            }
            //do something with error description, like show it to the user or send it to your log server  
}

If we pass the exception that generated the stacktrace in our first example, it will look like:

NullReferenceException
at ChaptersView.ChaptersTree_OnMouseMove (IL offset: 0x44)
at ChaptersView.GetPreviousCommandButton (IL offset: 0x28)

Step 2: Client sends you an exception/log that includes IL offsets
You can use Reflector or IL Disassembler (which comes with visual studio) to find out the piece of code that generated the exception.
I prefer IL Disassembler because Reflector will only show you IL code from those IL offsets, and there’s a large chance you don’t read IL as well as you read C#.

So you have to perform the following steps:
1) Go to start menu and start IL Disassembler
2) Inside IL Disassembler go to File->Open and load the dll (not the XAP) where the exception was thrown. (e.g. …\Release\Client.dll)
3) Go to View->Show source lines
4) Now navigate to the last method that appears in the stacktrace and we look after the IL offset from the stacktrace.
In our example above this is ChaptersView.GetPreviousCommandButton and has offset 0x28

Inside IL Disassembler we will see a mix of C# code and corresponding IL code:

  IL_001c:  brtrue.s   IL_0029
//000193:             {
//000194:                 throw new NullReferenceException(“Test Exception”);
  IL_001e:  ldstr      "Test Exception"
  IL_0023:  newobj     instance void [mscorlib]System.Exception::.ctor(string)
  IL_0028:  throw
//000195:             }
//000196:
//000197:             var previousCommandButton =
 

As you can see, at IL_0028 there’s the instruction that caused the exception.
This is IL code, but because we’ve checked “View->Show source lines” we also get the corresponding C# code just a few lines above.

//000193: {
//000194: throw new NullReferenceException();

So, in this case the exception was thrown because I’ve thrown it explicitly in order to show how IL offsets and IL Disassembler can be used to get an alternative to stack trace line numbers in silverlight.

Also please don’t just put that piece of code in every catch block. Create a method like “string GetStackTraceFromException(Exception ex)”
Another good idea would be to have some centralized error service, on the server side. You would then send those exception descriptions automatically along with method parameter values logged with PostSharp, whenever an error happens.
So by the time the client calls you, you have fixed the problem and he’s impressed ;)

Happy Debugging.

Written by Liviu Trifoi

April 21, 2011 at 6:15 pm

Creating a zip file with a folder in Silverlight

with 4 comments

If you happen to have a silverlight application that sends/receives files from the server side it’s a good idea to have those files compressed
Unless the files are already in some compressed format like (png, jpg, etc), this will reduce the amount of data sent through the network minimizing transfer times considerably.
So for textual file formats like xml, txt, etc I definitely recommend zipping them.
For zipping in silverlight I found two options at the time of this writing:
1) Use the System.IO.Compression.GZipStream
2) Use the SharpZipLib ported to Silverlight library.

I wouldn’t recommend the first option but for the simplest scenarios like: zip one file to one one compressed file.
If you need to create a zip archive that can contain multiple files & folders which are taken from the file-system or from in-memory content then I recommend the second option.
The only problem I had using option 2 is that documentation for sharpziplib is scarce, but persistent google searching does help.

So let’s take an example scenario and see how it’s done using SharpZipLib in Silverlight.
Suppose you have an in-memory xml, stored as a string, and the end result you want to achieve is an archive called test.zip which contains a single folder called Test.
Inside the folder you want to have the in-memory xml stored into an xml file called test.xml.
To see the end result easily we’ll write the archive to isolated storage.

So here goes the source code for the method that will do the creation of the archive:

        public byte[] GetCompressedByteArray(string content)
        {
            byte[] compressedResult;
            using (MemoryStream zippedMemoryStream = new MemoryStream())
            {
                using (ZipOutputStream zipOutputStream = new ZipOutputStream(zippedMemoryStream))
                {
                    // Highest compression rating
                    zipOutputStream.SetLevel(9);

                    byte[] buffer;

                    // The string to use as file content
                    using (MemoryStream file = new MemoryStream(Encoding.UTF8.GetBytes(content)))
                    {
                        buffer = new byte[file.Length];
                        file.Read(buffer, 0, buffer.Length);
                    }

                    // Write the data to the ZIP file            
                    ZipEntry entry = new ZipEntry("test/test.xml");
                    zipOutputStream.PutNextEntry(entry);
                    zipOutputStream.Write(buffer, 0, buffer.Length);

                    zipOutputStream.Finish();
                }

                compressedResult = zippedMemoryStream.ToArray();
            }

In the code above you can see how easily it is to create a virtual folder with a file in in a zip archive: ZipEntry entry = new ZipEntry(“test/test.xml”);.
Don’t be mislead though, although winrar and winzip will show you folders inside your zip archive, if you copy the archive to a mac/linux/android device you’ll still see only a file called “test/test.xml” since there the “/” doesn’t mean anything.
I haven’t had time to investigate this further but there’s some class ZipEntryFactory zef = new ZipEntryFactory().MakeDirectoryEntry(); which I think should be used for making directory entries.

So this GetCompressedByteArray method will return us a compressed byte array.
All we need to do now is to write it to isolated storage:

        public void WriteToIsolatedStorage(byte[] compressedBytes)
        {
            IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
            using (IsolatedStorageFileStream zipTemplateStream = new IsolatedStorageFileStream("test.zip", FileMode.OpenOrCreate, isoStore))
            using (BinaryWriter streamWriter = new BinaryWriter(zipTemplateStream))
            {
                streamWriter.Write(compressedBytes);
            }

        }

And write some test code:

          var xmlString =
@"<?xml version=""1.0"" encoding=""utf-8"" standalone=""no""?>
<book>
	<version>1</version>
	<language>english</language> 	
	<chapters>
       <chapter name=""chapter1"" />
       <chapter name=""chapter2"" >
    </chapters>
</book>";
            byte[] compressedXmlStringBytes = GetCompressedByteArray(xmlString);
            WriteToIsolatedStorage(compressedXmlStringBytes);

After running it, you should get a “test.zip” inside the isolated storage.
On Windows 7 the isolated storage is located at: c:\Users\username\AppData\LocalLow\Microsoft\Silverlight\.
Just search for a file named “test.zip”, inside the folders and subfolders at that location.

If you want to see the full actual, without searching for it, the only way is to use the visual studio debugger:
Put a breakpoint on using (BinaryWriter streamWriter = new BinaryWriter(zipTemplateStream)), then move the mouse over zipTemplateStream, non-public members, and look at m_FullPath, like in the image below:
See Image

Also see here the attached VS2010 solution.

For the unzipping part you can take a look at the Unpack a zip with full control over the operation

Happy zipping :)

Written by Liviu Trifoi

March 22, 2011 at 12:09 pm

Posted in Silverlight

Tagged with , , , ,