Showing posts with label XML. Show all posts
Showing posts with label XML. Show all posts

Wednesday, September 16, 2009

Adventures while building a Silverlight Enterprise application part #22

Yesterday I needed to check the available style keys in our main app.xaml file and see which are no longer needed. As there currently are 66 style keys in that file and it's growing, I didn't feel much for taking each key and searching through our source code to find out. Time to build a small tool. This article describes how I build this tool.

Requirements

The tool needs to be able to search a directory tree for files with a certain extensions (.xaml*) for a pattern or literal string. Before it does this it also needs to be able to open a .xaml file and retrieve any style elements so it can then read their keys.

To achieve this, two classes are needed. One class will read a .xaml file and get all keys from style elements and the other class will search trough the file system for files containing these keys.

Building it
I'll spare the obvious details and dive right into the highlights. To read the keys from style elements in basically any xml document, I used LinqToXml. Here is the code I used:
private void LoadStyleKeysFromDocument()
{
XNamespace winFxNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
XName keyAttributeName = winFxNamespace + "Key";

var result = from node in _document.Descendants()
where node.Name.LocalName.Equals("Style")
select node;

var distinctResult = result.Distinct();

StyleKeys.Clear();
foreach (XElement styleElement in distinctResult)
{
StyleKeys.Add(styleElement.Attributes(keyAttributeName).First().Value);
}
}


The first two lines make an XName object that is needed to include the xml namespace when retrieving the x:Key from the element. Note that this works independently from the prefix (x) as it was assigned in the document. This means that this code will still work if someone would decide to change the prefix on this namespace.

Next, a Linq query is used to retrieve any nodes in the document that have the name Style. The query is followed by a statement to make sure I only get unique results.

Finally I fill the StyleKeys collection with any key attributes value found inside an element in the query result.

Searching for a particular pattern in the file system is done in the following method:
public void Search(string pattern, string rootFolder, string fileFilter)
{
// Get all files matching the filter
string[] fileNames = Directory.GetFiles(rootFolder, fileFilter, SearchOption.AllDirectories);
// For each file
foreach (string fileName in fileNames)
{
// Open file
string fileData = File.ReadAllText(fileName);
// Match pattern
MatchCollection matches = Regex.Matches(fileData, pattern);
// Register count
PatternSearchResultEntry resultEntry = newPatternSearchResultEntry()
{
FileName = fileName,
HitCount = matches.Count,
Pattern = pattern
};
Results.Add(resultEntry);
}
}


As you can see, the first line gets all the filenames that are anywhere in the directory hierarchy below the supplied root folder.
Looping through the filenames, I simply load all the text from each file and use the Regex class to count the number of hits. By doing so, this code is also very useful to find hit counts for other patterns.
All the results are added to a collection of a struct called PatternSearchResultEntry.

So thats the business end of things. Obviously we need a user interface of some sort.
I chose a WPF interface, because I like data binding.
To retrieve user input for the style file and the folder to look in, I build a class called BindableString, which contains a Name and a Value and implements the INotifyPropertyChanged interface. It allows me to create instances of these and bind them to my UI. This way I have a central point to access this information without having to worry about updates, etc..

To do the actual work I wrote the following Click event for a button:
private void analyseStyleUsageButton_Click(object sender, RoutedEventArgs e)
{
XamlStyleKeyReader reader = newXamlStyleKeyReader();
reader.ReadXamlFile(_stylesFilePath.Value);

PatternSearch patternSearch = newPatternSearch();
foreach (string styleKey in reader.StyleKeys)
{
patternSearch.Search(styleKey, _searchRootDirectory.Value, new string[] { "*.xaml" });
}

CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(
patternSearch.Results);
if (view.CanGroup)
{
view.GroupDescriptions.Add(new PropertyGroupDescription("Pattern"));
}
analyseStyleUsageDataGrid.ItemsSource = view.Groups;
}

It basically instantiates the XamlStyleKeyReader class and loads the style file in it. Next it instantiates the PatternSearch class and kicks of a search for each style key available in the XamlStyleKeyReader.

The code after that groups the results based on the search pattern. The reason I did it this way is because it is not very transparent to bind to the result of a group in Linq. Binding to this is easy once you know how. As you can see the items source for the datagrid that displays my results, is actually the collection of groups.
This collection is declared as having objects, which isn't very helpful, however diving into the API documentation reviels that this collection contains instances of the CollectionViewGroup class. From that class I need the name (obviously) and a hit count, which of course it doesn't have.
To get a hit count I bound to the Items property from the group, which contains all the items that belong to that group and then I use a value converter to get the total hit count for that group.

I've uploaded the complete source for this tool here.

Be aware that this tool is far from finished. I would like to save the last settings and have some progress indication, which means moving the search code to it's own thread. Styling of the UI can be improved, etc., etc.

I do hope you find this code useful and you've learned something along the way.

Thursday, August 13, 2009

Pimpin' the blog part #2

In this episode of Pimpin' the blog we are going to have a look at how I will sync my data between Blogger.com and my new hosting platform. This involves a not well known feature from .NET in relation to RSS and using Linq2SQL. Eventually we'll end up with a tool that reads by Blogger RSS Feed and stores it in a SQL Server 2005 Database (or any other compatible database for that matter).

Thoughts on synchronization
As I laid out in part #1 I'm far from ready to give up my Blogger account as I still have many things to replace before I can do so. However I don't feel much for keeping two stores for the same information synchronized by hand. I have better things to do with my time than that (altough not that much better :-) ).
The first thing that came to mind was actually RSS as it keeps all the blog aggregate sites up to date as well, so why not use that? Besides, the final trigger to do all this was to customize my RSS feed in the first place, so why not use it as a source?
As a good developer I also went to see if I had any alternatives. I could opt for a HTTP/HTML spider, but it would be awkward, messy and complex. I could try and automate the export process for Blogger blogs, but again, awkward, messy and complex.

Loading a feed
So RSS it is then. The entire process is relatively simple:
  1. Get the feeds xml content
  2. Parse the feed into articles, etc.
  3. Store the articles and related data in the database
The first step is easy. Just take an HttpWebRequest and point it at the feed. Here is the code:

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(FeedUrl);
if (UseProxy)
{
request.Proxy = newWebProxy(ProxyUrl);
}

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();

So as you can see. it first sets up the HttpWebRequest, so it can get to the RSS Feed (using a proxy if needed). Then it just gets the response stream which then contains the XML for the RSS Feed.

The next step got me thinking. The first solution that popped into my mind was to use Linq2Xml. However that would involve a lot of code to get to all the different parts of information I needed. I googled around, read some blogs, until I ran into someone mentioning the SyndicationFeed object that's new in .NET Framework 3.5. I figured I would give that a try to see how it works and I could always go back to parsing the feed myself.

Here is the code to actually load the response stream into a SyndicationFeed instance:

XmlReader reader = XmlReader.Create(responseStream);

Feed = SyndicationFeed.Load(reader);

Wow, that was easy, now wasn't it? Keep in mind however that you do need to add a reference to both System.ServiceModel and System.ServiceModel.Web to make this work.
What I ended up with is a class that would handle loading the feed into a SyndicationFeed object that handled everything I needed in under fifty lines of code!

So that tackled step two of the process.
All that's left is to store it into the database. As I mentioned earlier, I chose to use Linq2Sql to handle this for me. Why? I have had extensive experience with Entity Framework and I do think that for large solutions it can be a good choice, however it does take a lot of effort to make it do what you want, which is not what I needed here.
I read up on Microsofts strategy on data access and why both Entity Framework and Linq2Sql are pushed and found out that Linq2Sql is actually meant to support RAD on smaller projects, or at least for smaller data access layers. As my data model only consists of three tables, I guess my project would qualify as small.



I'm not going to bother you with the details on how I stored my articles trough Linq2Sql and just go ahead and post a link to the code below.
The main program to control this is more interesting:

string feedUrl = ConfigurationManager.AppSettings[FeedUrlConfigKey];
RssFeedReader reader = newRssFeedReader(feedUrl);
reader.UseProxy = UseProxyTrueValue.Equals(ConfigurationManager.AppSettings[UseProxyConfigKey],
StringComparison.OrdinalIgnoreCase);
if (reader.UseProxy)
{
reader.ProxyUrl = ConfigurationManager.AppSettings[ProxyUrlConfigKey];
}
reader.ReadFeed();

foreach (SyndicationItem feedItem in reader.Feed.Items)
{
List<string> categories = newList<string>();
foreach (SyndicationCategory category in feedItem.Categories)
{
categories.Add(category.Name);
}
StorageConnection.AddArticle(feedItem.Title.Text, feedItem.Summary.Text, feedItem.PublishDate.Date,
feedItem.Id, categories.ToArray());
}


First I set up my RssFeedReader instance and call ReadFead on it. This results in a SyndicationFeed on which I iterate trough the Items collection. Then I get the categories and feed them into my StorageConnection class which makes sure everything is properly stored in the database. The StorageConnection class makes sure nothing is duplicated even if the same article is added more then once.

Here is the source:


In part #3 of this series, we'll look into building a new RSS feed with some customizations, based on the data we've retrieved today.

Wednesday, July 15, 2009

CodeEmbed4Web Beta 1 Release

Today it is my pleasure to announce to you the release of CodeEmbed4Web Beta 1. This public beta release of my new tool is available for download below.

As written in earlier posts, this tool allows you to copy code from Microsoft Visual Studio or another program that copies it's code in Rich Text Format, convert that code to other formats using predefined templates and then paste that converted code into any other program. The purpose of this tool is to quickly convert source code into publishable formats, like for example HTML, with a minimal effort and without limitation as to where it's going to be used.

With Beta 1, two templates are included:

  • CodeEmbed4WebXml.xslt allows you to get an exact copy of the XML generated by the tool. This enables you to build your own .xslt templates based on example XML files you can generate yourself.
  • ToHtml.xslt allows you to directly convert any code to html, so you can copy it into an html compatible program.
Feel free to add your own templates in the templates folder you find in the installation folder. New templates are automatically added to the tool as it starts up. If the tool is already started, please click the Refresh button that is below the list of templates.
The template you had selected last, will be selected when the tool starts.

Now without further delay, I present you with the download link:

CodeEmbed4Web Beta 1 (.msi)

If you need any support, found a bug, ran into an error, have any questions, suggestions or remarks, or you just want to let me know you are using CodeEmbed4Web Beta 1, please send an email to codeembed4web@gmail.com.

Update: Unfortunately I have recieved some reports of CodeEmbed4Web not being able to start. For some reason it throws an exception. I have been able to reproduce this behavior and I am looking into it. As soon as I figure it out, I will let you know. If you have this problem and if you are willing to provide me with some information on this, please send an email to codeembed4web@gmail.com.

Update: I've recently fixed the above issue and reposted the setup at the above link. I'll also release a simple patch soon.

I hope you all enjoy this tool and please provide me with feedback.

Wednesday, June 24, 2009

The birth of CodeEmbed4Web

I've been blogging here for some time now and I've been active on many forums and in several communities and I've always been annoyed by the fact that non of the media used has decent support for adding different kinds of source code and other technical content to them. Sure, a there are a lot of suggestions as how to do this, but they never really met my expectations. They either take to much effort or the result is not looking good enough.

Thinking about this the other day made me decide to make my own tool for this. I sad down, thought about my process of using technical content and I came up with how I felt the flow should be. Here is what I figured will work the best for me:
  1. Copy some code from Visual Studio
  2. Click a button in my tool / press some short-cut key combination
  3. Paste the result in whatever
Using these steps would have the least impact on my normal working flow and therefor make the most sense. There are some challenges, however. I would need the tool to detect whatever I put in to it and I would need it to know what format to convert it into. Especially that last step seems to be impossible. How would it know what I'm planning to paste my code into?
Thinking about that some more, I decided to scrap that last bit and add a small step to the flow:
  1. Copy some code from Visual Studio
  2. Choose a target if necessary
  3. Click a button in my tool / press some short-cut key combination
  4. Paste the result in whatever
Obviously I can still optimize that by making available more buttons or short-cut key combinations, but I didn't want to put in that much effort right at the beginning.

As I'm experienced in buildin Silverlight 2.0 applications I decided to use WPF as my technology. This allows me to access the clipboard and it has better keyboard support then Silverlight. Also, having to open a web application, has been one of the causes that using some of the existing tools takes to much effort.

I've been playing around with WPF and the clipboard and found out that VS (at least 2008) copies it's content to the clipboard using the RTF format. This drew me towards the RichTextBox control, so I placed one in my window and pasted the content into it and it looked great. I studied the documentation on the underlying FlowDocument technology and decided to run with it.

Now I've already built code to convert RTF to a FlowDocument instance (without the RichTextBox control, obviously) and then to XML, which will allow me to build several XSLT templates on top of that XML, which I can then apply to the XML to get to the end result.

Next steps will be:
  1. Test this with XAML
  2. Build templates for C# and XAML to convert to HTML (and maybe XAML?)
  3. Brush up the user interface
  4. Build a setup
  5. Release Beta 1
You've read that right. I will release this tool, and for free (at least for now). So if you're interested in this tool, please come back to my blog for more news or better yet, subscribe to my RSS feed on the top-right of this page.
If you have any question, suggestions or comments, you know the drill (that means, leave them below).

Sunday, January 4, 2009

Adventures while building a Silverlight Enterprise application part #3

So here we are again. Last time we looked at organizing the project and how it is important to address specifics in the teams culture. I promised some code for this episode, so a more technical subject is on the table today.

In this episode we will have a look at the intricacies of using multiple XAP files for our application. As you may remember from the first post, we expect this technique to help us reach some of the requirement goals we have, but we also identified some potential pitfalls with it.

As we implemented the basics of this we obviously ran into some issues that need solving. Below follow some topics to think about.

Silverlight will handle only one connection at any time
This may not seem obvious at first. If you haven't loaded a XAP file at runtime, you won't know this, so I figured I would give this some explanation. Whenever you load a XAP file you use the WebClient class to get the XAP file from the webserver. As this is done asynchronously, as any other communication, any other code you may invoke will simply execute will the XAP file is being downloaded. However, Silverlight will only allow you to have one connection at any time, so downloading multiple XAP files, or invoking any service calls for that mather, will throw an exception (as documented here).

As we load multiple XAP files at startup, one XAP file has to be downloaded after another. There are a couple of ways to solve this and it realy depends on the application design and requirements, but one thing is for sure: you don't want to bload this.

We chose to have an approach where one load completion leads to another load. In other words, one XAP files load is triggered by another XAP files completion event. We can do this, because one class, and one class only, is responsible for loading any XAP files and we were able to determine an order to load things in that will always work.

Another aproach you may want to consider if the above don't apply to your application (e.g. you can't determine a fixed order to load modules) is to have a queue for loading modules, where the completion of loading a module from the queue can trigger the loading of the next module, etc..

Loading UIElements from XAP files
But getting the XAP file is obviously only the first step in the process. The next step is to actually load the assemblies inside and, in our case at least, get a UIElement from one of these assemblies. To achieve this, we wrote a XapHelper class, that contains a static method to assist in the loading. The code looks like this:

public class XapHelper
{
private const string AppManifestFileName = "AppManifest.xaml";
private const string AssemblySourceAttributeName = "Source";
private const string ApplicationBinaryContentTypeName = "application/binary";

internal static UIElement LoadUIElementFromXap(Stream xapStream, string assemblyName, string className)
{
string applicationManifest = ReadApplicationManifest(xapStream);

XElement deploymentElement = XDocument.Parse(applicationManifest).Root;
IEnumerable<XElement> deploymentParts = from assemblyParts in deploymentElement.Elements().Elements()
select assemblyParts;

Assembly assembly = LoadAssemblies(xapStream, assemblyName, deploymentParts);

UIElement element = assembly.CreateInstance(className) as UIElement;
return element;
}

private static Assembly LoadAssemblies(Stream xapStream, string assemblyName, IEnumerable<XElement> deploymentParts)
{
Assembly assembly = null;
foreach (XElement assemblyPartElement in deploymentParts)
{
string name = assemblyPartElement.Attribute(AssemblySourceAttributeName).Value;

AssemblyPart assemblyPart = new AssemblyPart();

StreamResourceInfo assemblyResourceInfo = new StreamResourceInfo(xapStream, ApplicationBinaryContentTypeName);
Uri assemblyUri = new Uri(name, UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(assemblyResourceInfo, assemblyUri);

if (name == assemblyName)
{
assembly = assemblyPart.Load(streamInfo.Stream);
}
else
{
assemblyPart.Load(streamInfo.Stream);
}
}
return assembly;
}

private static string ReadApplicationManifest(Stream xapStream)
{
StreamResourceInfo manifestResourceInfo = new StreamResourceInfo(xapStream, null);

Uri appManifestUri = new Uri(AppManifestFileName, UriKind.Relative);
StreamResourceInfo applicationResourceStream = Application.GetResourceStream(manifestResourceInfo, appManifestUri);
Stream resourceStream = applicationResourceStream.Stream;
StreamReader streamReader = new StreamReader(resourceStream);
string applicationManifest = streamReader.ReadToEnd();

return applicationManifest;
}
}

As you can see, the main method here is LoadUIElementFromXap and you have to provide it with a stream that contains the XAP file. This stream would be the result of loading it trough the WebClient class. The second parameter is the name of the assembly to load the UIElement from and the third paremeter is the classname for the UIElement.

Also you may have noticed that the code is a little more verbose than some of the samples online. This is done to improve readability and maintainability of the code.

Identify XAP file split-ups
Another obvious question you will run into when using this aproach is, how will I split up my XAP files?

One way to look at it is to have a good look at your general screen design. What parts are always, or at least usually, the same? What parts change a lot?

Another important factor is size. After all, it all started out because of performance. So ask yourself, what parts of the interface are likely to become large and are not all needed at the same time?

Whatever rules you apply to this, one fact is very important. You should identify responsibilities that you need to host in the XAP files. What I mean by that is, you need to make sure you don't split up code that handles a single responsibility, breaking your OO design. Posible subjects for this are:

- Security
- Loading XAP files
- Data connections (altough this one is not likely)
- User settings

And obviously there could be many more, depending on the application your building.

In our case, loading XAP files and security were assigned to the outer XAP file as a responsibility. As we choose to have some navigation assigned to another XAP file, that resulted in loading the first, we created an interface, called ILoadModules, that identifies UserControls that want to load XAP files and supply the main XAP file with a delegate that it can set, to provide a method of doing so.

As I promised dsoltesz earlier I've uploaded a sample project.


I hope you liked the more technical side of this artice and I'm happy to have actually squezed in some code ;-). Please let me know if you have any questions, comments, etc..

Friday, November 21, 2008

Exception causes Xml Error in deserialization

This week I seem to run into quite a few nooks and crannies in the .NET framework that put me in front of some tricky issues. This time it had to do with deserialization, or so Visual Studio led me to believe.

Here is the situation. Last week I wrote some code that deserialized an xml file into an elaborate object model. Part of that code was to parse an xsd file and add some objects to the model from there. This all worked well for the past week, as proven by the unittests.

Yesterday I started writing some code to dynamicly load assemblies and classes based on some information from the xsd file. I didn't get to finish it, but as I started working on it this morning, all of a sudden it threw an exception on the deserialization code, stating that I had some error in my xml file. I checked my xml file, which I knew I hadn't changed, and off course it was fine.

So I figured that since the last change I made was in some code that parsed part of the xsd file, I would debug there. As it appeared, the exception occurred whenever I passed a certain XPathNavigator instance into a method of my Factory class for creating a plugin. My first tought was that this occurred because I passed the XPathNavigator to another method. I started to program around this approach, but to no avail.

I crunched my head on it for another half hour until I had to leave for a meeting, but as I came back and looked at my code I realized I actually called the initializer method of a Factory class that I use to load some pluggable classes. I started debugging this method and presto, it raised an exception, because of some small oversight. I fixed this exception and the deserializer code worked again.

Conclusion on this is that some code in the XmlSerializer or it's base classes, catches any exception thrown and re throws another exception which is not related to the actual problem. Fortunately, the inner exception does contain the actual exception, meaning I could have saved myself a lot of time and headaches, by simple looking an the inner exception.

Another thing I learned was that using a singleton pattern to create your factory class is a good thing, but you must pay some attention when debugging.

Wednesday, November 12, 2008

Using XmlSerializer to serialize type information

During the development of a project I'm currently working on, I ran into this. One property of a class I defined is called SimpleType and it holds a Type object. It contains some basic type like int or string.
Part of the project is to store this information and have it easily configurable, so my first thought was to use the XmlSerializer class to simply serialize the objects inside a collection to an xml file. So I wrote some code to do this:


XmlWriter writer = XmlWriter.Create(@"c:\temp\template.xml");
XmlSerializer serializer = new XmlSerializer(typeof(Template));
serializer.Serialize(writer, template);
writer.Close();


Running this code threw a nice exception: "The type System.Int32 cannot be used in this context". At first I was stunned. I didn't have any properties that even related to int. Then I figured it must be the SimpleType property and I needed some kind of workaround for this behaviour.
Here is the code of the property I tried to serialize:


public Type SimpleType { get; set; }


To make it work I started by adding an XmlIgnore attribute to the SimpleType property. This obviously prevents the serializer from including it into the xml file and stops the error from occurring, but now I had no type information in my xml file and I did need it.
So I added a private field to store the type in and added a second property called SimpleTypeName of type string.
The getter of this property simply returns the SimpleTypes Name property. The setter uses the static Type.GetType method to translate a typename into a Type object and sets it in the field.
Here is the code after I rewrote it:


private Type _simpleType;

[XmlIgnore()]
public Type SimpleType
{
get
{
return _simpleType;
}
set
{
_simpleType = value;
}
}

public string SimpleTypeName
{
get
{
if (_simpleType != null)
{
return _simpleType.Name;
}
else
{
return string.Empty;
}
}
set
{
_simpleType = Type.GetType(value);
}
}


To make this work you obviously need the namespace System.Xml.Serialization.

If you have any questions or remarks, please feel free to comment below.