Archive

Author Archive

CodeFluent Entities and ComponentOne

October 6, 2014 Leave a comment

CodeFluent Entities generates code which can be used easily with many third party component providers. We already show before how to use CodeFluent Entities with Syncfusion. Today we’ll see how easy it is to work with ComponentOne (C1) WPF components!

The sample application displays a list of users and their contacts using a ComponentOne DataGrid. Additionally you can export user list to Excel.

The solution contains 4 projects:

The CodeFluent Entities model is very simple:

The email has a validation rule to ensure you can only save a user with an invalid email address to the database.

The relation between User and Contact is configured to save contacts after user. This means that when you call User.Save, associated contacts are also saved. This functionality is very useful in a master-detail view as we are creating!

Now we can create the WPF application. Here’s the main part of the XAML:

<Window.Resources>
<!-- Convert blob to image -->
<design:BinaryLargeObjectValueConverter2 x:Key="BlobConverter"/>
</Window.Resources>

<Grid>

<c1:C1DataGrid x:Name="DataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" RowDetailsVisibilityMode="VisibleWhenSelected">
  <c1:C1DataGrid.Columns>
    <c1:DataGridImageColumn Binding="{Binding Photo, Converter={StaticResource BlobConverter}}" Header="Photo" IsReadOnly="True" />
    <c1:DataGridTextColumn Binding="{Binding FirstName}" Header="First name" />
    <c1:DataGridTextColumn Binding="{Binding LastName}" Header="Last name"  />
    <c1:DataGridTextColumn Binding="{Binding Email}" Header="Email"  />
    <c1:DataGridBoundColumn Binding="{Binding Contacts.Count}" Header="Contacts" IsReadOnly="True" />
  </c1:C1DataGrid.Columns>

  <!-- Handle validation using IDataErrorInfo (this will validate the Email property) -->
  <c1:C1ValidationBehavior.ValidationBehavior>
    <c1:C1ValidationBehavior/>
  </c1:C1ValidationBehavior.ValidationBehavior>

  <c1:C1DataGrid.RowDetailsTemplate>
    <DataTemplate>
      <StackPanel Orientation="Vertical">
        <TextBlock Text="Contacts" FontSize="14"/>

        <c1:C1DataGrid ItemsSource="{Binding Contacts}" AutoGenerateColumns="False" BeginningNewRow="C1DataGrid_BeginningNewRow">
          <c1:C1DataGrid.Columns>
            <c1:DataGridTextColumn Binding="{Binding FirstName}" Header="First name" />
            <c1:DataGridTextColumn Binding="{Binding LastName}" Header="Last name" />
          </c1:C1DataGrid.Columns>
        </c1:C1DataGrid>
      </StackPanel>
    </DataTemplate>
  </c1:C1DataGrid.RowDetailsTemplate>
</c1:C1DataGrid>

<Button Grid.Row="1" HorizontalAlignment="Left" Click="ButtonExportToExcel_OnClick">Export Users to Excel</Button>
<Button Grid.Row="1" HorizontalAlignment="Right" Click="ButtonSaveAll_OnClick">Save all</Button>

</Grid>

When the window is opened, we load all users:

private readonly UserCollection _userCollection;

public MainWindow()
{
  // Load all users and bind them to the grid
  _userCollection = UserCollection.LoadAll();

  this.DataContext = _userCollection;
}

To save all users and their contacts, we have to call SaveAll method:

private void ButtonSaveAll_OnClick(object sender, RoutedEventArgs e)
{
   // Thanks to the cascade save, contacts are also saved
   _userCollection.SaveAll();
}

When a contact is added, we have to set its User property with the selected user:

private void C1DataGrid_BeginningNewRow(object sender,
DataGridBeginningNewRowEventArgs e)
{
  var contact = e.Item as Contact;

  if (contact == null)
    return;

  var user = DataGrid.CurrentRow.DataItem as User;

  if (user != null)
  {
    contact.User = user;
  }
}

Finally we can export user collection to Excel:

private
void ButtonExportToExcel_OnClick(object sender, RoutedEventArgs e)
{
  DataGrid.Save("export.xlsx", FileFormat.Xlsx);
}

That’s it. With only a few lines of code, CodeFluent Entities and ComponentOne you can create a fully functional application.

The code sample is available on our GitHub repository: https://github.com/SoftFluent/CodeFluent-Entities/tree/master/Samples/SoftFluent.Samples.ComponentOne

Happy componenting,

The R&D Team

Getting started with the Blob Handler

October 6, 2014 Leave a comment

In ASP.NET, if you need to display a blob (Binary Large Object) such as an image, a video or a file, you’ll need to provide an URL to your display control. When storing blobs in database, a standard practice is to create a web page such as a blob.aspx to which you provide the blob’s id as parameter and which the page will load and display so that you can set your display control’s source to that URL.

Actually, CodeFluent Entities automatically generates a HTTP Handler which does all the work described before: thanks to it you’ll retrieve an URL pointing to your blob and which you’ll be able to use in your display controls.

To use it you need to register it in your web.config file as:

<system.web>
    <httpHandlers>
      <add verb="GET" path="blobhandler.ashx" 
type="<DefaultNamespace>.Web.HttpHandler, <DefaultNamespace>"/>
    </httpHandlers>
</system.web>

Or

<system.webServer>
    <httpHandlers>
      <add name="blobhandler" verb="GET" path="blobhandler.ashx"
type="<DefaultNamespace>.Web.HttpHandler, <DefaultNamespace>" />
    </httpHandlers>
</system.webServer>

Blob handler output types

 

The blob handler allows to get blobs in different manners to fit with common usages.

  • Raw: Use for downloading a File
  • Image: Use for displaying an Image

  • Thumbnail: Display a thumbnail of the Image (you can specify the desired height and width)


  • FileExtension: Display the File icon base on its extension (the same icon as in Windows Explorer)

  • FileExtensionSmall: Display the small Fileicon base on its extension (the same icon as in Windows Explorer)

To build the URL, you can use:

  • HttpHandler.BuildUrl(…)
  • BaseBinaryLargeObject.BuildHttpHandlerUrl(…)
  • ASP.Net controls: BinaryLargeObjectControl, BlobControl and BinaryLargeObjectField (located in CodeFluent.Runtime.Web)

For instance:

customer.Photo.BuildHttpHandlerUrl(BinaryLargeObjectUrlType.Raw)
customer.Photo.BuildHttpHandlerUrl(BinaryLargeObjectUrlType.Image)

Securing the blob handler

 

If you want to prevent some users to access the blob handler and so download files, you can write your own validation logic:

  • Add a partial class “HttpHandler.partial.cs”:

  • Then override the ResponseWriteBlob method and add your logic:
partial class HttpHandler
{
protected override bool ResponseWriteBlob(CodeFluent.Runtime.BinaryServices.BinaryLargeObject blob)
  {
    // Only administrators can access the blob handler
    return this.CodeFluentContext.User.IsInRole("Administrator");
  }
}

Server and client cache

 

Moreover blobs can be cached on the server and on the client to relieve the database. This feature is activated by default.

  • Server cache: When loading a blob property using CodeFluent Entities, it actually loads it from the database the first time and stores it on the disk; consequently, next calls won’t load it back from database anymore, unless a modification was done on the blob which will reload it and update the cache.
  • Client cache: Usage of the “Last-Modified” and “If-Modified-Since” http headers so the client download blobs only once.

Read more details about blob caching at http://blog.codefluententities.com/2011/11/09/codefluent-entities-blob-cache/

Happy storing,

The R&D Team

Member Format Expression

September 29, 2014 Leave a comment

Using CodeFluent Entities, you can use “Member Format Expressions” to customize the way names of entities and properties are formatted. We’ve already written before about the member format expression:

Today I’ll share the property format expression I use everyday. By default entities display property name and optionally type name:

Let’s create a new property format expression. Click the “Property Format” menu Item / “Choose”. Click the “Add New” button and copy the following format expression:

<if condition=IsEntityDisplay>-> </if> <if condition=IsNullable>({Name})<else />{Name}</if> : {DisplayTypeName} <if condition=”‘true’=Element.GetAttribute(‘localizable’,’http://www.softfluent.com/codefluent/patterns/localization/2008/1&#8242;)”>(Localizable)</if> <if condition=Relations.Count>({CascadeDelete})</if>

Now entities look like:

  1. The icon indicates the property is a member of the primary key
  2. Parentheses indicate the property is nullable
  3. “(Localizable)” indicates the property is localizable when using the Localization aspect
  4. “->” indicates the property is the entity display name
  5. The icon indicates the property type is an enumeration
  6. “(None)”, “(Before)” or “(After)” indicates the selected Cascade Delete option of the relation
  7. “*” and the infinite symbol indicate the property type is a collection

Thanks to the extensibility of the CodeFluent Entities modeler you can customize your working environment to fit your need. With this property member format, you visualize lots of information about your model in a breeze. Can you do that without CodeFluent Entities?

Happy formatting !

The R&D Team

Export your model as image

September 26, 2014 Leave a comment

Do you know that it’s possible to save the current Surface display in an image file ? It’s the easy way to share your model with someone.

You just need to right-click somewhere in the selected surface. Then you’ll see a new contextual menu with the following command:

Many formats are supported: PNG, BMP, GIF, WDP, JPG, and TIFF.

Here are some examples:

Happy exporting,

The R&D Team.

How to enable Intellisense for CodeFluent Entities runtime configuration?

September 16, 2014 Leave a comment

CodeFluent Entities generated code can be configured using the application configuration file (App.config or web.config):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="Sample"
     type="CodeFluent.Runtime.CodeFluentConfigurationSectionHandler,
           CodeFluent.Runtime" />
  </configSections>
  <Sample connectionString="<connection string>" useDateTime2="true" />
</configuration>

The configuration section is describe in the documentation: http://www.softfluent.com/documentation/BOM_ApplicationConfiguration.html.

This section is not known by Visual Studio, so you may have the following message:

ErrorXML

In fact Visual Studio doesn’t have an XML schema for this section and so it can’t validate it. At the same time we cannot provide a generic schema as the section name is Project specific. So the solution is to use The Template producer  which will generate the XML  schema based on the information from your Project.

  1.  

  2. Add a template producer

     

  3. Build the model
  4. Open the app.config or web.config file and add the following xml attributes (replace <Default namespace> by your project default namespace)

<configuration

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;

xsi:schemaLocation=”http://www.softfluent.com/<Default Namespace>/CodeFluentConfiguration.xsd CodeFluentConfiguration.xsd”>

You should now have auto-completion of the CodeFluent Entities configuration section.

binary services

 

 

 

 

 

 

 

Note: this xml schema includes only most common settings. If you think we forgot some useful settings, please leave a comment.

Happy configuration,

The R&D Team

Localize Dynamic Resources using an Aspect

September 15, 2014 Leave a comment

CodeFluent Entities handles static localization with the message concept. Static resources refer to all those UI messages that will never change throughout your application’s life-time: labels, error messages, information messages, titles, button texts, tool tips, etc.

CodeFluent Entities (Personal and Ultimate Edition) also handles dynamic localization out of the box. Dynamic resources refer to localized data created at runtime. For instance a web shop could have an international catalog in several languages, and this catalog should be displayed in a specific language depending on the users’ language (i.e. culture in .Net). Administrators add, remove or modify items from this catalog during the application’s life-time. Thus, administrators of the catalog will need to create catalog items with labels in several languages in order to support internationalization.

Let’s see how to use dynamic localization with CodeFluent Entities.

First, create an entity:

Then add the localization aspect:

Now we have to indicate the Description property is localizable:

That’s all. Yes you read that right! As a bonus you can define localized instances in the model:

Let’s generate the code and see what is generated:

The database contains two tables

The product table contains non-localized columns and the default value of the localized columns. The default value is used when no translation exists for one culture while loading row.

The table “ProductLocalized” contains translations:

The BOM is edited automatically but you can use it the same way as if there is no dynamic localization. Save and Load method use Thread.CurrentUICulture to know which description to load or save.

// First we create a product with an English description
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1033);
Product product = new Product();
product.Name = "Sample product";
product.Description = "A description in English";
product.Save();

// We create a French description.
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1036);
product.Description = "Une description en français";
product.Save();

// We can also add localization by using the static method SaveLocalizedValues
Product.SaveLocalizedValues(product, 1033, isDefault: true, description: "A description in English");

// Load products with an English description
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1033);
var productsEn = ProductCollection.LoadAll();

// Load products with a French description
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1036);
var productsFr = ProductCollection.LoadAll();

// Load products with a German description =&gt; There is no German description so the default value is used
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1031);
var productsDe = ProductCollection.LoadAll();

Localizing Dynamic Resources is very easy with CodeFluent Entities and the <a href="http://www.softfluent.com/documentation/BOM_LOC_DynamicResources.html">localization aspect</a>. Good news, this aspect is available out of the box!

Happy localizing,

The R&D Team

Categories: Aspects

Single Instance Application in .NET

September 10, 2014 Leave a comment

Running a single instance of an application is very easy with CodeFluent Runtime. Add the following nugget package: http://www.nuget.org/packages/CodeFluentRuntimeClient and use the SingleInstance class:

 
SingleInstance _singleInstance = new SingleInstance("Unique Name"); 

public MainForm() 
{ 

  if (!_singleInstance.WaitForMutext(IntPtr.Zero, IntPtr.Zero)) 
  { 
    Close(); 
  } 

  InitializeComponent();
}

If you want to make an action when the second instance is started, you can handle the windows message “”WM_” + uniqueName”:

 
protected override void WndProc(ref Message m) 
{ 
  if (m.Msg == _singleInstance.Message) 
  { 
    // your code
  } 
  base.WndProc(ref m); 
} 

SingleInstance class provides a helper to activate a Form, so when the second instance is started, it actually display the form of the first instance:

 
public partial class MainForm : Form 
{ 
  SingleInstance _singleInstance = new SingleInstance("My App"); 

  protected override void WndProc(ref Message m) 
  { 
  // Display the window of the first instance 
    _singleInstance.OnWndProc(this, m, true); 
    base.WndProc(ref m); 
  } 
} 

You can also force the instance to run, even if one is already running, by using the command line argument “/siForce” or “-siForce”.

 
$> myapp.exe /siForce 

Happy runtime exploration,

The R&D Team

Follow

Get every new post delivered to your Inbox.

Join 52 other followers