Milos Solution Platform (External Blog)

The Milos Solution Platform is .NET's premier platform for building business applications. This blog is meant for developers who use or evaluate Milos. This blog is used to share tidbits of information provided by the Milos developers at EPS. Many of the posts put the spotlight on new features. We generally recommend that all Milos users (developers) at least scan this blog to keep up with the Milos news.

Content Area Footer

Tuesday, November 16, 2010
Milos Name Components now support more standard types

We just released up updated version of the Milos name components that support more different standard types of communication information. In particular, we now support the following:

  • Twitter
  • Facebook (name and internal ID)
  • LinkedIn
  • Windows Live ID
  • Xing
  • YouTube

This update also includes an update of the UI components. So for instance, our standard name edit UI now features the following communication type drop down:

All the terms used are fully localizable, btw.

Posted @ 5:51 PM by Egger, Markus ( -
Comments (22)

Sunday, July 19, 2009
Silverlight ASP.NET Server Control Update

Here's a bit more on our ASP.NET Silverlight Control I talked about recently: We now updated this control to not just be compatible with the old control shipped by Microsoft, but to do things you might find useful. Here is a list of changes:

  • Default minimum version is now set to 3.0
  • Removed the ScaleMode property, since that just isn't supported by Silverlight anymore
  • Added the ability to very easily set that a control uses 100% of the available browser space
  • Added the ability to fire a storyboard in a splash screen XAML file
  • Added the ability to update a string in the splash screen that represents current download progress

Here is an example aspx file containing a Silverlight control (this one is from

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="D2SIGWeb._Default" %>
<%@ Register assembly="SimpleWebControls" namespace="EPS.Web.SimpleControls" tagprefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">

html xmlns="" >
head runat="server">
<title>D2SIG - Developers &amp; Designers Special Interest Group</title>
<form id="form1" runat="server" style="height: 100%;">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<cc1:Silverlight ID="Silverlight1" runat="server"


Note that there are no div tags required anymore (you can still add them if you want to, but it is handled by the control automatically). Also, no CSS styles have to be defined for the 100% height and width anywhere. Instead, the DisplayMode of the control is set to FullBrowser, which handles the 100% height and width right in all browsers.

Also note that this example fires a storyboard called "Loading", which is inside the resources of the D2SIGLoading.xaml file.

Furthermore, that XAML file has a text run called "ProgressLabel" which is automatically updated with the current download percentage rounded to full numbers. The XAML file has a text run inside a textblock that is defined like this:

<TextBlock Height="14"
Run x:Name="ProgressLabel"
FontFamily="Trebuchet MS"
Text="0"/><Run FontFamily="Trebuchet MS" Text="%"

Note that whatever object is specified as the progress update object must have a Text property of type string. Note that you can create custom objects with that property, which will automatically be updated as progress changes. You could then do whatever you'd like with that value, including parsing it as a number and use that for further calculations.


Posted @ 4:16 PM by Egger, Markus ( -
Comments (15)

Friday, July 17, 2009
A Silverlight 3 ASP.NET Host Control

Silverlight 3 has released, and with it have come some changes. One change is that the handy ASP.NET server control provided with Silverlight 2 is no longer supported. The official recommendation from MS is to simply embed client-side HTML tags (div and object tags) or use JavaScript to create an appropriate Silverlight embedding environment.

There certainly are upsides to that approach (flexibility and more customization), but there also are downsides (the control made things very simple, and it also allowed for code-behind access to properties on the control). Long story short: There really is no downside to having this control. For this reason, we recreated a Silverlight control 1:1 in the Milos Simple Web Controls assembly that you are probably already using in your ASP.NET apps. The control is 100% compatible. In fact, the only thing you have to change is the registration line of the assembly at the top of the .aspx file (the one that declares the "asp" namespace) so it points at SimpleWebControls.dll, rather than System.Web.Silverlight.dll file used by the Silverlight 2 SDK.

Oh, and btw: While we were at it, we made a few small improvements, such as a straightforward way to set the minimum required Silverlight version to 3.0.

 Note that this also includes the entire design time experience as well as required resources such as images, XAML, and scripts.


Posted @ 1:44 AM by Egger, Markus ( -
Comments (25)

Sunday, February 08, 2009
Self-Hosted WCF Cross-Domain Service Call Policies

Yesterday I blogged about a new Milos feature that allows to self-host Basic HTTP services, which is a feature that is useful when one has a service that is hosted using other bindings, but wants to expose the Basic HTTP binding in addition to others, which is typically done in Silverlight or browser scenarios (click here for yesterday's post).

When hosting Basic HTTP services for Silverlight, it is also important to know that Silverlight by default can only call services that are part of the same web application as the Silverlight app itself. This will practically never be the case when you self -host a Basic HTTP service. To allow that service to be called from Silverlight, the service must opt in to be callable across domains. (Note: Different ports also count as different domains in this case). This is a security restriction to avoid cross-site attacks.

Using the Milos self-host Basic HTTP feature, you can also enable cross-domain calling like so:


For instance, if you want to host a service that is available both over TCP/IP and Basic HTTP and allows cross-domain calls, it could be done like so:


Note that the cross-domain call only relates to HTTP based access, but not to other protocols.

Note also that the cross-domain call is enabled by means of a policy that is now available. You can browse to that policy using your web browser. For instance, if you run this in a test environment on localhost, you can now browse to http://localhost/clientaccesspolicy.xml, to see the exact settings that are exposed. This is what Silverlight accesses to allow a cross-domain call.

Note that it is possible to set additional parameters. In particular, you can specify which sites can make a cross domain call. For instance, if you only want to accept calls from and, you can restrict the cross domain calls in the following fashion:

ServiceGarden.AllowCrossDomainCalls(new Uri[] {
    new Uri(""),
    new Uri("") });

Note that these features are available on the ServiceGarden class as well as the development host. When the development host is used, the policy is listed in the UI as an additional service endpoint.


Posted @ 1:40 PM by Egger, Markus ( -
Comments (6)

Saturday, February 07, 2009
Self-Hosting Basic HTTP WCF Services

Milos provides a real simple way to develop and host (both in runtime as well as debug scenarios) WCF services. This is especially true for binary, TCP/IP based services that are great to use when both the client and the server are .NET applications. Another common scenario is hosting WCF services as HTTP and XML based web services. Especially with Silverlight, basic HTTP based services have gained more importance again. Of course, it is simple to host such services in IIS, and thus we have not provided any special features around that in Milos.

At least not so far. One of the scenarios people have pointed out to us (and frankly, we've run into ourselves too) is a deployment of the same service using multiple bindings. Why deploy one app for TCP/IP and then create a separate, ASP.NET based web app for XML web service support?

We have now created support for Milos aided, self-hosted Basic HTTP services. This is supported both in the ServiceGarden and development host environments. Here is an example of hosting a service in both TCP/IP and Basic HTTP configurations at the same time:


This example was from a runtime deployed service (likely hosted in a Windows Service). The following example shows the same service hosted in the development environment with support for both protocols.

var host = new TestServiceHost();

Accordingly, the ServiceClient class can now also natively open a connection to a Basic HTTP driven service. (Application configuration now supports "BasicHttp" as an additional service binding).


Posted @ 4:46 PM by Egger, Markus ( -
Comments (7)

Tuesday, January 06, 2009
Dynamic Property and Method Access

The upcoming version of Milos has a nifty little enhancement in the ObjectHelper class: It makes it easier to dynamically access/set properties and invoke methods. This is useful in scenarios that can otherwise only be handled with Reflection.

Example: Consider a scenario where a customer object is provided by some external system (perhaps from a dynamic language) and you need to access or set a name property. This can now be done like so in Milos:

object customer = GetCustomerObjectFromSomewhere();
string firstName = EPS.Utilities.ObjectHelper.GetPropertyValue<string>(customer, "FirstName");
EPS.Utilities.ObjectHelper.SetPropertyValue(customer, "LastName", "Smith");

Note that these methods are also available as extension methods. To use the extension methods, the EPS.Utilities namespace has to be included at a file level, by putting the following using statement at the top of your source file:

using EPS.Utilities;

Now, the above code can be simplified to the following:

object customer = GetCustomerObjectFromSomewhere();
string firstName = customer.GetPropertyValue<string>("FirstName");
customer.SetPropertyValue("LastName", "Smith");

Milos now also makes it easier to invoke methods dynamically. For instance, one can call a method ont he same object like so:

string name = customer.InvokeMethod<string>("GetFullName", null); 

Note that the second parameter is an array of parameters that get passed to the method. For instance, if the GetFullName() method takes an integer and a string parameter, it could be passed like so:

object[] parameters = { 0, "Test" };
string name = customer.InvokeMethod<string>("GetFullName", parameters); 

Note that C# 4.0 (once released) will provide features to also make it easier to do these things. In C# 4.0, the following syntax would be valid:

dynamic customer = GetCustomerObjectFromSomewhere();
string firstName = customer.FirstName;
customer.LastName = "Smith";
string name = customer.GetFullName(1, "Test");

The example used here, with the Customer object dynamically retrieved somewhere is one scenario where this is useful. There are other scenarios as well, where generic code is written that can operate on types that are defined elsewhere. Data binding scenarios are one example.


Posted @ 9:47 AM by Egger, Markus ( -
Comments (8)

Saturday, December 20, 2008
Object casting convenience methods

This upcoming version of Milos has a nice little enhancement in the utilities namespace. The DataHelper class now has extension methods that make it very convenient to cast from object types (such as fields in DataSets) to their real types.

These helper methods are implemented as extension methods. To use them, you have to add this line of code at the top of your program:

using EPS.Utilities;

Now, the extension methods are automatically available on all objects. For instance, you can do the following:

DataSet myDs = this.GetSomeDataSet(); // Assume that we somehow get a DataSet
DataRow row = myDs.Tables[0].Rows[0];
Guid myGuid = row["id"].ToGuidSafe();
string myString = row["name"].ToStringSafe().Trim();
int myInt = row["number"].ToIntegerSafe();

The main advantage here is that these methods always return valid values, even if the cast object is not valid. For instance, these methods are aware of System.DBNull and they also trap errors.

There are a number of different such methods, including the ability to cast to booleans, DateTime, decimal, and so forth (all common value types, basically).

Posted @ 2:03 PM by Egger, Markus ( -
Comments (8)

Friday, October 24, 2008
Some Enhancements to the Document Management Components

The upcoming build of Milos has a few small but important enhancements for the digital Document Management components.

Most important is the improved support for ASP.NET's routing framework (introduced with ASP.NET 3.5 SP1). This enhancement allows for an arbitrary download URL for file attachments in web applications. For instance, one can create the following URL (or any other arbitrary chosen URL):

A route and handler can be set up for this URL like so:

public static class RoutingSetup?
    public static void RegisterRoutes?(RouteCollection? routes)
        routes.Add(new Route("Downloads/{DownloadId}/{FileName}?", new FileAttachmentDownloads?()));

public class FileAttachmentsDownloads? : IRouteHandler?
    var handler = new EPS.Web.DocumentManagementUI.RequestHandler?();
    Guid downloadId = new Guid(requestContext.RouteData.GetRequiredString("DownloadId?"));
    handler.AttachmentId = downloadId;
    return handler;

Other enhancements include more automatically determined content types for web downloads (in particular XAML is of importance) and also a few added icons in the windows file attachment grids (MP3 and XAML in particular).


Posted @ 11:49 PM by Egger, Markus ( -
Comments (6)

Thursday, October 23, 2008
Background Style of Office Edit Forms

Milos edit forms in WinForms that use the office style usually render a background pattern similar to Microsoft Word or Excel. Some people ask to turn that off (and how to achieve that). It is quite simple, actually:

Office edit forms have a property called RenderOfficeBackground. If that property is set to false,  the normal background color of the form (whatever that property might be set to) is rendered, instead of the fancy Office background pattern.

Posted @ 6:03 PM by Egger, Markus ( -
Comments (5)

Thursday, October 23, 2008
Non-Key Auto-Increment Fields

Here's a small Milos feature addition that could be of interest to some people: We now support auto-increment fields that aren't key fields. In the past, we only supported such fields when they were in fact key fields (and there is quite a bit of functionality Milos has specific to that). In the latest version, such fields can be any field in the database.

Note that it only makes sense to expose such fields as read-only properties in business entities. Also, there is some additional work that needs to be done on the side of the developer to pick up the newest values generated by the database whenever such data gets saved the first time. (And of course, there is some overhead in database access and round trips that should not be underestimated).

Also, be aware that we do NOT recommend using this feature whenever the incremental field is used for business logic. Business logic belongs in the middle tier and not the database.

So this is a feature that may be valuable but it also should be deployed somewhat carefully. But there you have it: It's now supported.

Posted @ 4:43 PM by Egger, Markus ( -
Comments (25)

Tuesday, June 03, 2008
General Milos News

During the week of May 5-9 EPS have hosted the first Milos University training course at the EPS Houston office. The first half of the event was lecture style, presenting the core aspects of Milos, such as its architecture and main components for the data, middle, and UI tiers, and lots of new features have been shown, such as our first components for building WPF applications with Milos, framework components and tools for building service-oriented applications (using WCF), the new DataLoadController component for improved usability and testability, the new framework for unit and integration tests of middle-tier components, the new logging and exception publishing/handling components, new components for building ASP.NET web applications, etc.

The second half of the event was hands-on, and a WinForms application was built with every attendee going through the entire process, step-by-step, including writing unit and integration tests for the middle-tier classes. This sample application will be cleaned up and made available for people to download and play with it soon.

Today we are also rolling out a new version of Milos components, including updated whitepapers and tools. If you are a Milos user, you will be getting the updates through email.

Below is a list of some important things included in this new build.


  • Components for building WPF applications using the well-known architecture available in other Milos user-interface components, such as multi-threaded data loading operations, ease-of-use data binding, etc.

Milos Services

  • Components and tools for building service-oriented applications (and WCF) with Milos.


  • Improvements for data binding all around
  • A new data edit panel which mimic WinForms style edit form development more closely on the web
  • JQuery support
  • Integrated resource handler
  • Overlay panel for client side dialogs


  • A SimpleListPane class to handle panes that launch edit forms.
  • Added capability to work with new DataLoadController



  • Added simple support for deletion business rules
  • Added full support for serialization of business entities


  • Improved service for saving byte array data (such as Bitmaps)
  • Implemented ExecuteScalar method. It supports queries such as "SELECT Column FROM Table WHERE Field = Value", and it'll always return the value of the first column, in the first row, in the first table (in case the query returns more than that). Notice that the XML Data Service does not currently support queries with aggregators, such as "SELECT Count(*) FROM Table".
  • The service is now read-write when working with data as “embedded resource”. This means that the data can be queried and updated, but that all happens in-memory, so whenever the application is restarted, it uses the original data.


  • This framework has almost been written from scratch, and it replaces the previous UnitTestFramework and IntegrationTestFramework components.
  • This new framework addresses several limitations found on the previous ones, and it adds a lot more hooks and features, allowing developers to easily achieve a good code coverage of their business objects and entities.

Code Analysis rules

  • Fixes to several false positives

Business Layer Designer (previous called “Business Entity Generator”)

  • Several bug fixes
  • Improved support for using either Generic or custom collections
  • Added support for applying any of the business rules that come out of the box to properties on the entity.
  • Added support for specifying a different base class for business entities.
  • Added support for specifying a Default Fields and Default Order for the GetList method on business objects.

There is a lot more to come, but we will save that for later.

Posted @ 3:43 PM by Egger, Markus ( -
Comments (9)

Wednesday, April 16, 2008
Data Load Controllers

We have recently introduced a fully-automatic way of creating external data loading mechanisms. This is achieved by means of so-called "data load controllers". So what is the basic idea behind these? Well, I am glad you asked! :-)

Milos provides great ways to load data in all kinds of data edit forms, from Windows to the Web, in all kinds of variation. For instance, one can simply use the SetEntityType<>() method to automatically load an entity of a certain type in a window or a web form. It is also possible to override LoadContents() and LoadSecondary() data methods to load additional data, or load it in slightly different ways.

This makes for easy ways of loading data. However, in some scenarios, we want to go even further. (We will always continue to support this approach as it provides the basis for all operations, but we want to provide more options). There are a few scenarios we want to simplify. Here are those considerations:

  1. This approach generally relies on inheritance. That is OK in many scenarios, but in some scenarios (such as ASP.NET web forms or WPF/Silverlight XAML), there are scenarios where one just wants to use an object instance for data loading. For instance, one might want to put a data panel into a web form without explicitly subclassing it. Those scenarios are currently supported by means of an event model. That is not a bad approach, but it is slightly different from the inheritance model, and the written code is not IL-compatible, since method signatures are differently, and so forth.
  2. Different interfaces may have a need to load the same data. For instance, 10 different forms of a windows application may need to load certain lookup tables. Or, an ASP.NET web form may need to load the same exact data as the WinForms or WPF equivalent. Neither the inheritance, nor the event model allows for simple code reuse in these scenarios.
  3. It is very hard to unit test data loading for UIs if the code is embedded in, or attached to the user interface classes.

We now provide an additional abstract option: All the data loading (and data handling) code can be put in an abstract class. Here is an example of such a class:

public class NameEditLoader : DataLoadController
    public override void Configure()

    public override object LoadSecondaryData()
        NameBusinessObject names = NameBusinessObject.NewInstance();
        DataSet dsNames = names.GetList();
        return dsNames;

If you are familiar with current Milos loading code, then you will recognize all of this, because the code is identical to code that would go into a Windows Forms class as well as other types of UI classes. The main difference is that this code now sits in an external class. This class can now be used in an interface class. For instance, it could be used in a Windows Form or a WPF window like so:

public MyWindow() // Constructor
    this.DataLoadControllers.Add(new NameEditLoader());

The same exact object can also be used on a web form:

protected void Page_Load(object sender, EventArgs e)
    this.dataEditPanel1.DataLoadControllers.Add(new NameEditLoader());

The same object could also be used in XAML, or in a mobile app, and so forth. Also, the object can now be used stand-alone in unit test scenarios, which is extremely important in test driven development (TDD) and other scenarios where unit tests are needed. (And most applications need unit tests these days).

So we think this is a cool change. It is completely optional and everything that was there before is still available. But going forward, this is clearly the recommended approach.


Posted @ 4:08 AM by Egger, Markus ( -
Comments (5)

Thursday, April 10, 2008
Milos Web Development supports jQuery

Have you ever used jQuery? ( It is a very cool JavaScript library that makes all kinds of client-side HTML development much easier. The most recent version of Milos web control (ASP.NET) now use jQuery for internal stuff and it is also available for you to use in your own client-side efforts. Whenever you include SimpleWebControls.dll in one of your projects, you automatically get access to jQuery stuff. All you have to do is include a script reference, as well as the Milos resource HTTP handler in the web.config (which you should always have anyway). So the web.config needs to have this:

    <!-- Other stuff here... -->
<add verb="*" path="Milos_simplewebcontrols_*.aspx"

With this in place, you can simply add a <script> element to your page to get the jQuery features:


Note: This aspx page does not really exist. Whenever this URL gets hit, Milos intercepts the call and returns a dynamically generated script stream to the client.

With this in place, you can now add jQuery stuff like this:

$(document).ready(function() {
    alert("Main document content loaded!");

For more information on jQuery syntax and features, visit, or get one of the many jQuery books out there (the jQuery site lists several).

Note: Milos also uses jQuery features for some of its advanced scripting. For this reason, it could happen that the script reference gets included multiple times, which could lead to unexpected results. For that reason it is better to add the script reference in the Load() event of the page (or a control) using this code:

if (!Page.ClientScript.IsClientScriptIncludeRegistered("JQuery"))

This automatically adds the script reference from above, but it only adds it if the reference isn't there already.

There is a lot of cool stuff that can be done with jQuery, from simplified event handling to relatively advanced (for HTML) visual effects. Milos uses this for a number of things, such as the cool new overlay dialogs. But that is a topic of a different post... :-)


Posted @ 1:03 PM by Egger, Markus ( -
Comments (8)

Friday, April 04, 2008
Lessons learned - Little new ones, big old ones

We’ve got an in-house application that we’re working on as a training exercise.  Like most projects of this type we find ourselves relearning old lessons.

We wanted to extend the functionality of the standard windows DateTimePicker control by creating a new composite control with a DateTimePicker and adding spinners for hours/minutes.  We started out with the DateTimePicker and two spinners (pretty obvious first step) and gave the class a DateTime property to hold the core DateTime value.  We then data bound the DateTimePicker and the two spinners to the DateTime property.  The DateTimePicker was bound to the DateTime property and the spinners were hooked up to the hour or minute components of class’ DateTime property.

We wired everything up and tried running the shell application.  Every time we touched the composite control we got exceptions revolving around one of the constituent controls (dtPicker or spinner) having a null value.  Mike Yeager wandered in and made the fateful observation that we had “grossly over engineered” the composite control by having each constituent control separately data bound to the same property.  After all, the entire DateTime value was stored within the dateTimePicker control.

We removed the databinding of the two spinners to the DateTime property and created properties for hours and minutes that were based on the existing hour/minute components of the dateTimePicker.  The getter of the hours/minutes properties returned the hour or minute component of the DateTime value in the dateTimePicker.  The setter of the properties called a method that concatenated the year/month/day components of the dateTimePicker with the values of the hour and minute spinners into a new DateTime value.  The spinners were hooked up to the hour and minute properties.

It took about 15 minutes to scrap the old code, reassemble the controls and properties, and then bind everything together.  It worked on the first try!

  • The “new” lesson learned was specific and almost trivial: When extending the functionality of a multi-faceted control, use that control’s internal value as the basis for your work rather than reinvent the (DateTime value) wheel by pushing three separate controls at one value.
  • The “old” lesson is: “Think about what you’re going to do before you even touch the keyboard.  You should have a clear vision of your objective before writing the first line of code."

    Claudio will be amplifying on this in his blog, complete with code samples.

Posted @ 4:13 PM by Chichester, Thom ( -
Comments (3)

Tuesday, February 05, 2008
Exception Handling and Logging Framework

Milos has always provided features around exception handling. In this upcoming build however, we have formalized a lot of the functionality (and added to it as well) to create two distinct sub-frameworks:

  1. An Exception Handling framework
  2. A Logging framework

The idea is the exception logging framework is pretty simple: Whenever an exception occurs that remains unhandled, that exception can be "published" to the exception framework via a so-called "Exception Mediator" object. This object receives the exception and then passes it on to all kinds of interested listeners that can be registered with the mediator. Such listeners could be UI components to show exception information to the user (listener as well as UI components are provided by default and can be extended), or the information can be emailed to an administrator, or perhaps the information needs to be logged. The framework also includes components that can be used to retrieve detailed exception information such as an exception hierarchy or the current call stack.

The logging framework can be used to log various information ("events") to different destinations. For instance, it is possible to log events to text files or XML files of various formats. It is also possible to log to the Windows system log on the local machine or a remote machine. Furthermore, it is possible to log to email recipients or the Console or message boxes, or... And of course, it is also possible to easily combine all these loggers and even extend them with your own.

In addition to the class reference that includes examples for all these features, we have also written 2 whitepapers that explain the use of these frameworks.

Posted @ 4:55 PM by Egger, Markus ( -
Comments (6)

Thursday, January 17, 2008
Generic Sub Item Collections in Business Entities

The latest Milos version has a pretty neat enhancement in the business entity model: Sub item collections are now available as generics. Here's why that's cool:

So far, in order to create collections of sub items in business entities ("1-to-many relationships"), one had to create the individual item objects, as well as a collection class that could hold those items. The trouble with that is that it is a lot of work to create the collection class, and the only benefit of this class is a strongly typed interface. (The strongly typed interface is needed so one can access parent.Children[x] and then get all the properties on that object).

Using the new generic version of the sub item collection, one usually does not have to create a subclass. Instead, one just creates the class for the individual items, and then instantiates the generic version of the collection, with the generic being the item type.

Example: An invoice entity with a line item collection could simply instantiate an appropriate collection like so:

protected override void  LoadSubItemCollections()
   this.colLineItems =
       new GenericEntitySubItemCollection<LineItem>(
         this.GetInternalData().Tables["LineItems"] );

For more details and a detailed explanation, consult the "How-To: Creating a Collection of Child Items" topic in the Milos documentation.

Of course, the old way is still supported as well. The main benefit of using the generic version is in creating collections by hand. When using any of the code generator tools, one isn't exposed to the collection anyway (in most cases), so the benefit is minimal. So far, the code generator tools do not use the generic collection yet. There are considerations around backward compatibility. However, we are considering to change the tools in the future...

Posted @ 4:05 PM by Egger, Markus ( -
Comments (4)

Wednesday, December 05, 2007
IBindingList Support on Sub Item Collections

Here is a small feature I really hope everyone appreciates, considering how hard it was to support it in a nice way: All sub item collections in Milos now implement IBindingList, which is a fancy way of saying that they can now be bound to pretty much anything that supports data binding.

In the past, most of the Milos controls supported binding to sub-item collections, but with third party controls, it was hit and miss. Adding support for this interface (in addition to the interfaces we supported previously) pretty much covers the whole range now.

Posted @ 11:39 AM by Egger, Markus ( -
Comments (7)

Saturday, October 13, 2007
'Split-Table' Table Updated

Here is a new feature that only some people will need, but those who need it really do... ;-)

The Milos BusinessObject class features a SaveTable() method, with takes a DataTable as a parameter (among other things) and can then (by means of using various DataService features) simply persist all the changes in the data table back to the database server (whether that's SQL Server or some other database technology). This feature is used extensively by the BusinessEntity infrastructure (among other things). So for instance, when you load a business entity that has a master table and several child tables, each of the tables inside the entity is saved using the SaveTable() method.

However, it has been brought to our attention that people sometimes like to load tables into entities or DataSets that are not just simple tables, but they may be created by joins that incorporate multiple tables. In that case the SaveTable() method was not able to save the table, since every record in the DataTable really mapped to different tables in the database. We have now added a feature to Milos that can handle this scenario in many (although not all!) cases. The basic idea is this: We provide a new SaveTable() overload with parameters that allow you to indicate which fields to include in the save operation, and what the table name maps to, and even field maps in case some of the fields are renamed.

So let's say you created a join that returned a table that has fields from a Contacts table, such as ContactID (maps to ID), FirstName, LastName, and also fields from a 1:1 joined CustomerInformation table like CustomerID (maps to ID), CustomerNumber and CreditLimit. You could save this information back to the database in a two-step operation, like so:

string[] contactFields =
    new string[] { "ContactID", "FirstName", "LastName" };
Dictionary<string, string> contactFieldMaps =
    new Dictionary<string, string>();
fieldMaps.Add("ContactID", "ID");
bool retVal = this.SaveTable(
    existingDataSet.Tables["CustInfo"], "ID",
    "Contacts", contactFields, contactFieldMaps, false);

if (retVal)
    string[] contactFields = new string[]
        { "CustomerID", "CustomerNumber", "CreditLimit" };
    Dictionary<string, string> contactFieldMaps =
        new Dictionary<string, string>();
    fieldMaps.Add("CustomerID", "ID");
    bool retVal = this.SaveTable(
        existingDataSet.Tables["CustInfo"], "ID",
        "CustomerInformation", contactFields,
        contactFieldMaps, true);

In this example, the first SaveTable() operation is limited to the ContactID, FirstName, and LastName fields. Also, the primary key for the Contacts table is really ID, so we create a map for that. (This works for all fields, not just primary keys). If that save is successful, we perform a second save operation for the remaining fields. Not that in the second operation, we pass a true as the last parameter, which flags the data table as unchanged in memory (this is not done after the first save, since other changes still exist).

So this works nicely, but there are a few things you need to know. First, this works best if the table contains 1:1 relationship data. In one-to-many scenarios, the parent "record" exists multiple times, and thus really shouldn't be updated. You can still use the same functionality to update the information from the second part of the table, but you should be very careful updating the parent information, since it will potentially result in multiple updates that can each override each other. Another potential issue is that in memory, each record only has one record state. So the record is either flagged as unchanged, deleted, modified, or added. However, if the parent-part is modified, but the child-part should be considered added, then that would not work and the generated update statements would be incorrect and potentially fail, or - worse - cause incorrect data to be written to the database. So be careful with that.

One aspect of this that isn't immediately obvious is that this new functionality can also be used in scenarios where you just query a single table, but the update needs to map field names, or limit the update to certain fields. For instance, if an empty string array of field names is passed to this method and a mapping dictionary is passed, then all fields will be saved, but they can be mapped. Or, you can pass an empty dictionary, but pass a limiting list of field names, to exclude certain fields from update. Both scenarios can be very useful in a number of scenarios.


Posted @ 11:48 AM by Egger, Markus ( -
Comments (8)

Friday, October 12, 2007
Minor String-Array Helper Method

This is a pretty small item, but I find it useful in a lot of scenarios: There now is a new ArrayContainsString() method on the StringHelper object. It provides a quick way to check whether a certain string array contains a certain string, and it can do so in a case insensitive fashion:

string[] testArray = new string[] { "One", "Two", "Three" };
bool result1 = StringHelper.ArrayContainsString(testArray, "one", true); // returns true
bool result2 = StringHelper.ArrayContainsString(testArray, "one");       // returns false
bool result3 = StringHelper.ArrayContainsString(testArray, "One");       // returns true
bool result4 = StringHelper.ArrayContainsString(testArray, "Four");      // returns false

As I said, this is not an earth-shaking feature, but it is kinda nifty...

Posted @ 2:26 PM by Egger, Markus ( -
Comments (4)

Sunday, September 09, 2007
Automatic Window Title Updates on Navigation

Here is a small but nice tweak: When using navigation UIs, in particular the Office application forms, or the Developer Express application forms, Milos now supports automatic updates of the windows title (the secondary title, actually), from the pane's caption (the pane the user navigates to). This behavior is optional, and can be controlled by means of the UpdateWindowSubTitleFromNavigation property, which can be found on all app form classes.

Note: Related to this change is an update to the INavigationHost interface, which now features a NavigationCompleted event. If you implement this interface somewhere, you simply need to add that event to your implementation as well. The code required to do so is simple:

/// <summary>
/// Occurs after a navigation.
/// </summary>
public event System.EventHandler NavigationComplete; 

Whether you actually use the event or not is up to you. However, we recommend you call if after navigating, which is done in the Navigate() method that goes with the same interface. Here is the new standard implementation for that method: 

/// <summary>
/// Triggers a navigation based on the specified URI
/// </summary>
/// <param name="uri">URI to navigate to</param>
/// <param name="ignoreNavigationHistory">Defines whether the current navigation needs
/// to be added to the navigation history. For instance, a go-back operation is already
/// in the history and thus does not have to be added, while a navigation to a new location
/// has to be added to the history.</param>
/// <returns>True if navigation is successful</returns>
public bool Navigate(string uri, bool ignoreNavigationHistory)
    bool retVal = NavigationHelper.Navigate(uri, this.History, this, ignoreHistory,
        this.ForwardControls, this.BackwardControls, this);
    if (this.NavigationComplete != null)
        this.NavigationComplete(this, new EventArgs());
    return retVal;

That's it! Small change, but nice to have.


Posted @ 3:09 AM by Egger, Markus ( -
Comments (12)

More Posts: Older Posts








Syndication RSS 2.0 RSS 2.0

All My Blogs:
My personal blogs:
Dev and Publishing Dev and Publishing
Travel and Internat. Living Travel and Internat. Living
Other blogs I contribute to:
Milos Blog (US) Milos Blog (US)
VFPConv. Dev Blog (US) VFPConv. Dev Blog (US)
VFPConv. Dev Blog (DE) VFPConv. Dev Blog (DE)


Blog Archives
All Blog Posts

    November (1)
    July (2)
    February (2)
    January (1)
    December (1)
    October (3)
    June (1)
    April (3)
    February (1)
    January (1)
    December (1)
    October (2)
    September (2)
    July (1)
    June (2)
    May (4)
    April (6)
    March (8)
    February (3)
    January (2)
    December (2)
    November (2)




This Blog is powered by MilosTM Collaboration Components.