Archive

Archive for the ‘ASP.NET’ Category

ASP.NET Identity and CodeFluent Entities

February 20, 2014 Leave a comment

The ASP.NET Identity system is designed to replace the previous ASP.NET Membership and Simple Membership systems. It includes profile support, OAuth integration, works with OWIN and is included with the ASP.NET templates shipped with Visual Studio 2013.

ASP.NET Role and Membership providers are out of the box features provided by CodeFluent Entities. Today we’ll see how to create an ASP.NET Identity implementation with CodeFluent Entities.

Let’s do this ! :)

What do we have to do?

ASP.NET Identity provides a bunch of interfaces to define Users, Profiles, Logins, Roles, and how to store them.

A user is defined by the Microsoft.AspNet.Identity.IUser interface and a role is defined by the Microsoft.AspNet.Identity.IRole interface. Those interface are very generics:

public interface IUser
{
    string Id { get; }
    string UserName { get; set; }
}

public interface IRole
{
    string Id { get; }
    string Name { get; set; }
}

ASP.NET Identity also introduce the concept of user store to persist user information. There are different levels of functionalities depending of your needs:

Finally, the Microsoft.AspNet.Identity.UserManager is a higher level API that will coordinate different components such as the UserStore, the Password hasher and the user and password validation in order to manage users in your application.

Now you should have understood that to do our custom ASP.NET Identity we’ll implement the IUser, IRole and IUser*Store interfaces (yes all of them).

Let’s create the model


CodeFluentEntitiesAspNetIdentity

User must implement the IUser interface. This can be done by adding an implementation Rule. The same apply for Role with the IRole interface.

To ensure the uniqueness of the username and role name we declared them at CollectionKey. This will also add automatically the methods User.LoadByUserName and Role.LoadByName.

To implement the UserStore we’ll need two more methods. The first one is to find a customer by a provider key. To do so we add a CFQL method on the user entity:

LOADONE(string providerKey) WHERE ExternalLogins.ProviderKey = @providerKey

We also need to delete a claim by User, Type and Value. This can also be done by CFQL

DELETE(User, Type, Value) WHERE User = @User AND Type = @Type AND Value = @Value

Those methods will be translated into stored procedures during the build process. Note that with CFQL you don’t have to bother with JOIN nor types ! :)

Below is a part of UserStore and RoleStore implementation :

public class UserStore :
    IUserStore<User>,
    IUserPasswordStore<User>,
    IUserSecurityStampStore<User>,
    IUserRoleStore<User>,
    IUserLoginStore<User>,
    IUserClaimStore<User>
{

    public Task CreateAsync(User user)
    {
        if (user == null) throw new ArgumentNullException("user");
        return Task.Run(() => user.Save());
    }

    public Task DeleteAsync(User user)
    {
        if (user == null) throw new ArgumentNullException("user");
        return Task.Run(() => user.Delete());
    }

    public Task<User> FindByIdAsync(string userId)
    {
        return Task.Run(() => User.LoadByEntityKey(userId));
    }
// ...
}

public class RoleStore : IRoleStore<Role>
{
    public Task CreateAsync(Role role)
    {
        return Task.Run(() => role.Save());
    }

    public Task<Role> FindByNameAsync(string roleName)
    {
        return Task.Run(() => Role.LoadByName(roleName));
    }
// ... 
}

Now we can use the UserStore through the UserManager and the RoleStore through the RoleManager:

new UserManager<User>(new UserStore())
new RoleManager<Role>(new RoleStore())

In the article we show that the code generated by CodeFluent Entities can easily be used with really new Framework like ASP.NET Identity. This is possible as CodeFluent Entities generates rock-solid foundation on which you can build your application !

The full implementation is available for download.

Happy user storing,

The R&D team.

Exploring the CodeFluent Runtime: Web Controls – Part 2

February 5, 2014 1 comment

In Part 1 of this series, we looked at some useful controls from the CodeFluent.Runtime.Web assembly.
On the same subject, we’ll explore in this post some other very useful controls for ASP.NET WebForms application.

The first controls are DataSource controls; They aren’t visual but very convenient as they can be bound to any DataBound controls like GridView, ListView, etc.

CountryDataSource (CodeFluent.Runtime.Web.UI.CountryDataSource) gives you a list of countries with a lot of properties, including localization information (EnglishName, NativeName, Location, Region, etc.). The type of the enumerated item is CodeFluent.Runtime.Utilities.Country. You can learn more about this type in the related article on our blog.

<cfe:CountryDataSource ID="CountryDataSource1" runat="server"/>
<asp:GridView ID="GridView2" runat="server" DataSourceID="CountryDataSource1" AllowPaging="true">

CountryDataSource

CultureDataSource (CodeFluent.Runtime.Web.UI.CultureDataSource) gives you a list of CultureInfo (System.Globalization.CultureInfo) and can be bound with any DataBoundControl (GridView, DropDownList…).

<cfe:CultureDataSource ID="CultureDataSource1" runat="server" />
<asp:GridView ID="GridView3" runat="server" DataSourceID="CultureDataSource1" AllowPaging="true">

CultureDataSource

CodeFluent Entities comes with another cool Web Control: the CultureDropDownList.

CultureDropDownList (CodeFluent.Runtime.Web.UI.WebControls.CultureDropDownList) displays automatically for you a DropDownList filled with cultures. With a single line of code, you can let the user change the UI Culture of your website.
First, add this control to your page:

<cfe:CultureDropDownList id="cultures" runat="server" CultureCookieName="culture" AutoPostBack="true" TitleMemberName="EnglishIEStyle" TextMemberName="NativeName" CultureList="en-us;fr-fr" />

The CultureList property lets you set the cultures you want to display. By default, all available cultures (on the current computer) are loaded.

Then, just add the following code in the Global.asax file.

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
    CultureDropDownList.SetRequestCulture(Request, "culture"); 
}

The second parameter corresponds to the name of the cookie set in the CultureDropDownList in the page.

Because the CultureDropDownList control is set to AutoPostBack=”true”, when the user selects another culture, the website page will automatically reload with the selected culture. Of course, you need to put in place the ASP.NET globalization mechanism and provide the corresponding resources files :).

FreeForm Control
Now, another topic. Let’s imagine you have several forms to implement as pages on your site, most of them used to get simple input from your users. Let’s suppose you want to send email with the content of the forms. This can be useful for polls for example.

For this, you can use the FreeForm control (CodeFluent.Runtime.Web.UI.WebControls.FreeForm). It allows you to create an arbitrary form, add all the child controls you want to it and then add a piece of code to gather all the user input data. Here is a quick example.

We start with a simple markup:

<cfe:FreeForm ID="FF" runat="server" OnFormChanged="OnFormChanged" DecamelizeOptions="Default" >
    <ItemTemplate>
        <asp:Panel ID="Panel3" runat="server" GroupingText="Personnal Information">
            <asp:Label ID="Label1" runat="server" Text="Preferred Name:" /><br />
            <asp:TextBox ID="TextBox1" runat="server" Text='<%#Bind("PreferredName") %>' /><br />
            <asp:Label ID="Label2" runat="server" Text="City:" /><br />
            <asp:TextBox ID="TextBox3" runat="server" Text='<%#Bind("City") %>' /><br />
        </asp:Panel>
        <asp:Panel ID="Panel4" runat="server" GroupingText="Business Information">
            <asp:Label ID="Label3" runat="server" Text="Your Company:" /><br />
            <asp:TextBox ID="TextBox4" runat="server" Text='<%#Bind("YourCompany") %>' /><br />
            <asp:Label ID="Label4" runat="server" Text="Describe your primary role and function:" /><br />
            <asp:TextBox ID="TextBox5" runat="server" Text='<%#Bind("DescribeYourPrimaryRole_x0026_Function") %>' /><br />
        </asp:Panel>
        <br />
        <asp:Button ID="Button2" runat="server" Text="OK" />
    </ItemTemplate>
</cfe:FreeForm>

We have a form with 4 textboxes and their corresponding labels into 2 panels, plus a standard button to submit :

When the user submits the button, the whole input data will be transformed into a dictionary instance automatically. Each control will provide a dictionary entry in that instance. Notice that all the Text attributes of the textboxes have a standard ASP.NET bind token attached. That token will become the entry field key, and the entry value will be the data entered by the user (whatever the type of this data and the type of the control). To get this dictionary you just need to attach to the FormChanged event and read the Values property of the FormChangedEventArgs parameter, like this:

<script runat="server">
    protected void OnFormChanged(object sender, FormChangedEventArgs e)
    {
        StringBuilder sb = new StringBuilder();

        foreach (DictionaryEntry de in e.Values)
        {
            sb.AppendLine(de.Key + "=" + de.Value + "<br/>");
        }
        
        // NOTE: instead, send email here with the content of the StringBuilder
        litResult.Text = sb.ToString();
    }
</script>     

You may have noticed that we have defined the field names using camel-case and also some weird hexadecimal notation. The FreeForm control has the ability to “decamelize” these keys and unescape the Unicode characters represented by their hexadecimal values. This trick allows us to use anything for key names (although the Bind syntax is much more restrictive). You can define several options in the DecamelizeOption attribute (None, ForceFirstUpper, ForceRestLower, UnescapeUnicode, UnescapeHexadecimal, ReplaceSpacesByUnderscore, ReplaceSpacesByMinus, ReplaceSpacesByDot, KeepFirstUnderscores, DontDecamelizeNumbers, KeepFormattingIndices).

So, this simple example gives you the following result:

Of course, you will hopefully implement something more useful in your project :) You can also imagine having a form generator for power-users, letting them design simple forms and process the Key/Value Dictionary generated by the FreeForm control in a pretty much automatic way.

NumericTextBox Control
Do you need a numeric-only textbox input?. CodeFluent.Runtime.Web has a solution for you: the NumericTextBox control.

The NumericTextBox control (CodeFluent.Runtime.Web.UI.WebControls.NumericTextBox) prevents user from entering non-numeric characters. You can define the value type with the TargetTypeName attribute, define the MaximumNumbers, MaximumIntegerNumbers, MaximumDecimalNumbers or the Negative or Positive Sign. Note this control can be used inside a FreeForm control we say previously.

<cfe:NumericTextBox ID="NumericTextBox1" runat="server" Value='<%# Bind("NumberOfEmployees") %>' TargetTypeName="System.Int32" />

There is also associated DataControlField, NumericTextField CodeFluent.Runtime.Web.UI.WebControls.NumericTextField) fields controls that you can use in GridView, DetailsView, etc.

<cfe:NumericTextField DataField="Age" HeaderText="Age" TargetTypeName="System.Int32"/>

Captcha Control
The Captcha control (CodeFluent.Runtime.Web.UI.WebControls.CaptchaControl) displays an image with some simple text inside, but supposedly quite difficult to read for machines. You can define the image size, the complexity of the produced image, and a timeout duration. Notice that the image is generated by the BinaryLargeObjectHttpHandler of CodeFluent Entities (Learn more about Blob here).

The Captcha control comes with its validator, the CaptchaValidator control (CodeFluent.Runtime.Web.UI.WebControls.CaptchaValidator). As any validator, you just need to declare the ControlToValidate and the CaptchaControlID associated.

In this example, we just display a message if the text entered corresponds to what was generated by the Captcha control.

<cfe:CaptchaControl ID="CaptchaControl1" runat="server" Width="200px" Height="50px" Expiration="120"
    Options="FontWarpFactorMedium, BackgroundNoiseLevelHigh,LineNoiseLevelHigh" />
<br />
Please enter the code or press F5 to refresh the browser
<br />
<cfe:CaptchaValidator ID="CaptchaValidator1" runat="server" ControlToValidate="Verify" CaptchaControlID="CaptchaControl1"
    SetFocusOnError="True" ErrorMessage="The code doesn’t match or there was a timeout" ForeColor="Red" />
<br />
<asp:TextBox ID="Verify" runat="server" EnableViewState="False" AutoCompleteType="None" />
<asp:Button ID="btValidate" runat="server" Text="Validate" OnClick="btValidate_Click" /><br />
<asp:Label ID="lblResult" runat="server" Text="You enter the correct text! Thank you for validating." Visible="false" ForeColor="Green"/>

In the button Click event, call Page.IsValid to validate the captcha:

<script runat="server">
    protected void btValidate_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            lblResult.Visible = true;
        }
        else
        {
            lblResult.Visible = false;
        }
    }
</script> 

Have a look at the Captcha image here:

Captcha

As you’ve seen in this serie, CodeFluent.Runtime.Web can be very useful to us, web developers who are tired to write a lot of code-behind to do simple actions. With these controls you just need to drag and drop them on your page, save and enjoy.

These controls are located in the CodeFluent.Runtime.Web assembly, part of the CodeFluent Entities product ! Try them!

Happy controling!

The R&D team.

Exploring the CodeFluent Runtime: Web Controls – Part 1

January 28, 2014 1 comment

Today, on the series “Exploring the CodeFluent Runtime” we’re going to explore the ASP.Net Web Controls inside the CodeFluent.Runtime.Web namespace. This is all provided as part of CodeFluent Entities.

In the CodeFluent.Runtime.Web assembly, you’ll find several controls usable in ASP.Net WebForms applications. The first we’ll see are controls used to render UI relatively to the data (bindings).

BooleanControl (CodeFluent.Runtime.Web.UI.WebControls.BooleanControl) displays what’s defined in FalseTemplate or TrueTemplate according to a boolean value.

<cfe:BooleanControl ID="BooleanControl1" runat='server' Value='<%# Eval("MyBooleanValue") %>' AutoBind="true">
    <TrueTemplate>
        This template will be displayed if Value is evaluated as "true"
    </TrueTemplate>
    <FalseTemplate>
        This template will be displayed if Value is evaluated as "false"
    </FalseTemplate>
</cfe:BooleanControl>

CompareControl (CodeFluent.Runtime.Web.UI.WebControls.CompareControl) displays FalseTemplate or TrueTemplate according to what’s defined by the ValueToCompare attribute and an Operator (Equal, NotEqual,
GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, DataTypeCheck). For the DataTypeCheck operator, the ValueToCompare will be the full name of the type to check.

<cfe:CompareControl ID="CompareControl1" runat='server' Value='<%# Eval("MyValueToCompare") %>' Operator="GreaterThan" ValueToCompare="0">
    <TrueTemplate>
        Value is greater than 0
    </TrueTemplate>
    <FalseTemplate>
        Value is less than or equal to 0
    </FalseTemplate>
</cfe:CompareControl>
 
<cfe:CompareControl ID="CompareControl2" runat='server' Value='<%# Eval("MyValueToCompare") %>' Operator="DataTypeCheck" ValueToCompare="System.Int32">
    <TrueTemplate>
        Value is a System.Int32
    </TrueTemplate>
    <FalseTemplate>
        Value is not a System.Int32
    </FalseTemplate>
</cfe:CompareControl>

MultiCompareControl (CodeFluent.Runtime.Web.UI.WebControls.MultiCompareControl) is similar to the CompareControl but is more like a switch.

<cfe:MultiCompareControl ID="MultiCompareControl1" runat="server" Value='<%#Eval("MyValueToMultiCompare") %>'>               
    <case ValueToCompare="10" Operator="GreaterThan">
            Value is greater than 10
    </case>
    <case ValueToCompare="0">
    Value is equal to 0
    </case>
    <default>
    Value is not equal to 0 and is less than or equal to 10
    </default>
</cfe:MultiCompareControl>

ExistsControl (CodeFluent.Runtime.Web.UI.WebControls.ExistsControl) displays FalseTemplate or TrueTemplate depending on a given value. The value is tested against “null”, “DBNull”, or an empty string (possibly trimmed).

<cfe:ExistsControl ID="ExistsControl1" runat='server' Value='<%# Eval("Email") %>' Trim="true">
    <TrueTemplate>
        This template is displayed only if Value is not null or empty 
    </TrueTemplate>
    <FalseTemplate>
        This template is displayed when Value is null
    </FalseTemplate>
</cfe:ExistsControl>

When you work with enumerations into your Model, you want to be able to display and edit them easily into your forms or GridView. We have a solution for you! Let me introduce the Enum Controls.

EnumCheckBoxList (CodeFluent.Runtime.Web.UI.WebControls.EnumCheckBoxList) derives from the standard CheckBoxList control but is automatically filled with the fields of the enumeration type you define EnumTypeName parameter. Note this also supports multi-valued enumerations (with a [Flags] custom attribute).

EnumRadioButtonList (CodeFluent.Runtime.Web.UI.WebControls.EnumRadioButtonList) derives from the standard RadioButtonList control. As the EnumCheckBox, you only need to define the EnumTypeName attribute

EnumDropDownList (CodeFluent.Runtime.Web.UI.WebControls.EnumDropDownList) derives from the standard DropDownList and works the same way.

Another control that allows you to quickly bind your data is the BoolControl (CodeFluent.Runtime.Web.UI.WebControls.BoolControl). The BoolControl is a visual custom control that displays a System.Boolean or Nullable<System.Boolean> bound value. Depending whether the value is nullable or not, it can display a True/False or True/False/Undefined visual. It can use a CheckBox, DropDownList, horizontal button list, ListBox or horizontal or vertical radio button list to display these 2 or 3 items. It also supports read-only rendering and custom texts, interesting for localization purposes.

Is Customer:

<cfe:BoolControl ID="BoolControl1" runat="server" Value='<%# Bind("IsCustomer") %>' TrueText="Yes" FalseText="No" UnspecifiedText="Undefined" BoolControlType="HorizontalRadioButtonList" />

Contact Method:

<cfe:EnumCheckBoxList ID="EnumCheckBoxList1" runat="server" Value='<%# Bind("MethodToContact") %>' EnumTypeName="BlogCFE.ContactManager.ContactMethod" />
Origin (RadioButton):
<cfe:EnumRadioButtonList ID="EnumRadioButtonList1" runat="server" Value='<%# Bind("Origin") %>' EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />
Origin (DropDown):
<cfe:EnumDropDownList ID="EnumDropDownList1" runat="server" Value='<%# Bind("Origin") %>' EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />           

Here is the result:

For each of these controls, an associated DataControlField exists so you can use them in GridView, DetailsView, etc.

<cfe:BoolField DataField="IsCustomer" HeaderText="Is Customer" TrueText="Yes" FalseText="No" BoolControlType="DropDownList" />
<cfe:EnumCheckBoxListField DataValueField="MethodToContact" HeaderText="Contact method" EnumTypeName="BlogCFE.ContactManager.ContactMethod" />
<cfe:EnumRadioButtonListField DataValueField="Origin" HeaderText="Origin (RadioButton)" EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />
<cfe:EnumDropDownListField DataValueField="Origin" HeaderText="Origin (DropDown)" EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />        

the result in a grid view:

List of Contacts

As you’ve seen, these controls can avoid you to write a lot of code focusing more on a declarative way of programming.

In the next article, we’ll introduce the DataSources controls and another couple of cool utilities.

The R&D team.

Exploring the CodeFluent Runtime: The Template Engine

December 26, 2013 Leave a comment

As you probably know, we released a few year ago the CodeFluent Runtime as a free Nuget Package named CodeFluentRuntimeClient. This is a set of utilities which is usable across all types of .NET applications (WPF, WinForms, ASP.NET, console, Windows service, etc.) and aims to ease the developer’s life.

Today, I’d like to introduce you, as part of the Exploring the CodeFluent Runtime series, an easy-to-use class to generate documents from a template source file.
You should ask yourself what is a template in term of software development. It’s simply a mixture of text blocks and control logic that can generate an output file. With our template engine, the control logic is written in JavaScript as fragments of program code. By default, the engine is based on the fast IE9+ “chakra” JavaScript engine developed by Microsoft for its Internet Explorer web browser.

Before we go any further it’s important to briefly describe the two following classes from the CodeFluent.Runtime.TemplateEngine namespace:

Template: Defines properties and characteristics of an ActiveX Scripting template and provides a set of methods to load and process a template file.

ParsedTemplate: In-memory and compiled representation of your template file (JavaScript).

The following diagram shows how the template engine internally works:

CodeFluentRuntimeClient Template

If you want to understand how to parse and execute JavaScript by C#, just have a look to this StackOverflow discussion. You’ll find how to interop with the JavaScript “IE9+ Chakra” JavaScript engine.

The easiest way to understand how to use the template engine is by way of an example. The first thing we have to do is create our template file.

Consider the following Rtf input file:

RTF Input file

Rtf Input file

You can download the template file here.

The “<% %>” tag represents the JavaScript code blocks. Let’s use the Template engine in order to process the template described above:

// The ComVisible indicates that the managed type is visible to COM.
[ComVisible(true)]
public class OrderLine
{
    public string ProductName { get; set; }
    public decimal UnitPrice { get; set; }
    public int Quantity { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // initialize the argument dictionary.
        IDictionary<string, object> arguments = new Dictionary<string, object>();
        arguments.Add("orderLine1", new OrderLine() { ProductName = "Product A", Quantity = 5, UnitPrice = 12 });
        arguments.Add("orderLine2", new OrderLine() { ProductName = "Product B", Quantity = 10, UnitPrice = 30 });
        arguments.Add("orderLine3", new OrderLine() { ProductName = "Product C", Quantity = 4, UnitPrice = 40 });

        CodeFluent.Runtime.TemplateEngine.Template template = new CodeFluent.Runtime.TemplateEngine.Template();

        // Load the source template with the argument initialized above.
        template.Load("PurchaseOrder_Template.rtf", arguments.Keys.ToArray());

        using (StreamWriter writer = new StreamWriter(@"PurchaseOrder.rtf"))
        {
            // Run the template using the CodeFluent Runtime Template engine.
            template.Run(writer, arguments);
        }
    }
}

For running this code you have just to reference the CodeFluent Runtime Client Library and when executing it you’ll get the generated output file :

Rtf Output file

Rtf Output file

It’s good to know that the template engine is fully extendable. It would be helpful if you want to add your own keywords or business rules. For this purpose, you should inherit from the Template and/or ParsedTemplate objects.

On the same topic and through the CodeFluent Entities product, we are shipping a Template producer which is an engine that allow developers to generate text files from template containing C# code blocks.

Happy templating,

Antoine Diekmann

Using flags enumeration with ASP.NET MVC and CodeFluent Entities


 

Enumeration support

 
 
CodeFluent Entities provides full support of “enumeration” types and multi value enumerations (flag enumeration).
 

Enumeration support

Enumeration support


 
To declare a multi value enumeration, go to the enumeration type properties and set the, go to the enumeration type properties and set the Multi Value property to True.
 
Multi Value flag

Multi Value flag


 
And since the build version (646) you can set an enumeration value as the combination of other values (by their name).
 
Enumeration value

Enumeration value


 

Using enumeration values with ASP.NET MVC

 
Let’s use these concepts on an ASP.NET MVC application, I will use the model above as an example. I also have a MediaController with an Index action to list all Medias and an Edit action (Get and Post).
 
The default template for an enumeration value is a textbox, so if I write something like this:

@Html.EditorFor(m => m.MediaType)

 
I will get a textbox for my enumeration value.
 

Textbox for enumeration value

Textbox for enumeration value


 
This will work but the user will have to write a correct enumeration value, and unless each user knows all the possible enumeration values, this is not an acceptable solution.
 
It would be better to display a dropdown list instead. Let’s create a template named Choice.cshtml on the Views\Shared\EditorTemplates folder.
 

@model Enum
@{
var items = from object value in Enum.GetValues(Model.GetType())
select new { Value = value, Text = value.ToString() };
SelectList list = new SelectList(items, "Value", "Text", Model);
}
@Html.DropDownList("", list)

 
And now if we choose this as the template for our enumeration:
 

@Html.EditorFor(m => m.MediaType, "Choice")

 

Dropdown list for enumeration

Dropdown list for enumeration


 
This works fine and we can use the Choice.cshtml template for any enumeration type.
 

Using multi enumeration values with ASP.NET MVC

 
Let’s now do the same work for a multi value enumeration (flag enumeration). First we create a template named MultiChoice.cshtml on the Views\Shared\EditorTemplates folder.
 

@model Enum
@{
var items = from object value in Enum.GetValues(Model.GetType())
select new { Value = value, Text = value.ToString() };
IEnumerable selected = CodeFluent.Runtime.Utilities.ConvertUtilities.SplitEnumValues(Model);
MultiSelectList list = new MultiSelectList(items, "Value", "Text", selected);
}
@Html.DropDownList("", list, new { multiple = "multiple" })

 
We use here a method on the CodeFluent.Runtime.Utilities namespace to split a flag value into a list of enumeration values.
Let’s try it for our multi value enumeration.
 

@Html.EditorFor(m => m.ReleaseFormat, "MultiChoice")

 

Multiple dropdown list for enumeration

Multiple dropdown list for enumeration


 
This seems to work but it doesn’t, when I try to save my form, not all values are saved (from the flag multi value enumeration). This is because MVC does not bind correctly the multi value enumeration to my model.
 
We need to add a custom model binder (System.Web.Mvc.IModelBinder) and a value provider (System.Web.Mvc.IValueProvider). I will use some utilities classes that are used for the ASP.NET Web Site V2 producer, they can be found under the Templates folder in the CodeFluent Entities installation location (Program Files (x86)\SoftFluent\CodeFluent\Modeler\Templates\UI\AspNetMvc\Code\Utilities.cs.tpl). I will copy the content of the file in my ASP.NET MVC project filling the correct namespace. Don’t forget to add a reference to the CodeFluent.Runtime.Web assembly.
 
EntityBinder and EntityValueProvider

EntityBinder and EntityValueProvider


 
Finally, we register the EntityBinder and the EntityValueProviderFactory classes that we have just added. On the Application Start:
 

ValueProviderFactories.Factories.Add(new EntityValueProviderFactory());
ModelBinderProviders.BinderProviders.Add(new EntityBinder());

 
This time everything works great.
 
This post was inspired by the CodeFluent Entities templates when wondering what the ASP.NET Web Site V2 producer generates Winking smile.
 
 
Regards,
 
 
Pablo Fernandez Duran
 
 

Using ServiceStack with CodeFluent Entities

March 6, 2013 Leave a comment

In our last blog post we saw how to create a REST service layer using ASP .NET Web API and a CodeFluent Entities model.

Now we are going to use ServiceStack to expose HTTP web services (JSON and XML) from an existing CodeFluent Entities model.
ServiceStack is a REST Web Service Framework for .NET, it is an open source project that you can find here.
ServiceStack is based on a ‘modular’ architecture and it was built to be used in a simply way, no XML configuration and no code generation.
The ‘philosophy’ behind ServiceStack is to use strong-typed DTOs to define a web service API.
To illustrate this post we are going to use the Car Rental Sample project.

CarRental Sample  project

CarRental Sample project



We will add a Persistence producer (SQL Server 2012 for me) and a Business Object Model (BOM) producer.

Producers

Producers



ServiceStack can be used as a standalone solution or can be integrated on a MVC application, we are going to use it in an empty ASP .NET web application.

ASP .NET Web Application

ASP .NET Web Application



First of all we need to install ServiceStack in our ASP .NET web application project via nugget:

       PM> Install-Package ServiceStack

Now we need to register ServiceStack in our configuration (web.config), we want to host ServiceStack at the root path (‘/’) so we use this configuration:

<system.web>
  <compilation debug="true" targetFramework="4.5" />
  <httpRuntime targetFramework="4.5" />
  <httpHandlers>
    <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/>
  </httpHandlers>
</system.web>

If you want register ServiceStack on a custom path to avoid conflicts with another web framework (eg. ASP .NET MVC) go here.

ServiceStack uses a particular structure for services, a service consists in:

  • A request DTO
  • A service implementation
  • A response DTO

We are going to create a service that handles CRUD operations for the Entity ‘CarGroup’ (you can add some instances to your model so we have some test data).

We start by creating the request DTOs:

[Route("/carGroup", "GET")]
public class GetAllCarGroupRequest : IReturn<CarGroupCollection> { }

[Route("/carGroup/{Id}", "GET")]
public class GetCarGroupRequest : IReturn<CarGroup>
{
    public int Id { get; set; }
}

[Route("/carGroup/{Id}", "DELETE")]
public class DeleteCarGroupRequest
{
    public int Id { get; set; }
}

As you can see we also have associated some routes to our requests.
For the create and update methods (POST and PUT) we will add the request configuration elsewhere because we want to use existing classes as requests (the CarGroup class that will be the object to add or update), we will see this further in this post.
Now we need to create our service and it operations. I will call my service ‘CarGroupService’ and it will inherit from the class ‘ServiceStack.ServiceInterface.Service’.

public class CarGroupService : ServiceStack.ServiceInterface.Service
{
}

ServiceStack will ‘match’ a request to an operation and associate HTTP actions (verbs) to the name of our operations, so our operations must follow some conventions:

public {ResponseDTO} {HTTPVerb}({RequestDTO} request)

Now we can create our operations.

To retrieve all our CarGroup objects:

public CarGroupCollection Get(GetAllCarGroupRequest request)
{
    CarGroupCollection carGroups = CarGroupCollection.LoadAll();
    return carGroups;
}

To retrieve one CarGroup by its id:

public CarGroup Get(GetCarGroupRequest request)
{
    CarGroup carGroup = CarGroup.Load(request.Id);
    if (carGroup == null)
    {
        throw new HttpError(System.Net.HttpStatusCode.NotFound, "Car Group not found");
    }
    return carGroup;
}

To add a new instance of CarGroup or to update an existing instance we will use a common method:

private HttpResult CreateUpdate(CarGroup carGroup)
{
    if (carGroup == null || !carGroup.Save())
    {
        return new HttpResult(System.Net.HttpStatusCode.BadRequest, "Error while saving.");
    }
    return new HttpResult(carGroup, System.Net.HttpStatusCode.OK);
}

And we will call this method for create (POST) and update (PUT) operations:

public HttpResult Post(CarGroup request)
{
    return CreateUpdate(request);
}
<br/>
public HttpResult Put(CarGroup request)
{
    return CreateUpdate(request);
}

Finally, to delete an instance of CarGroup:

public HttpResult Delete(DeleteCarGroupRequest request)
{
    CarGroup carGroup = CarGroup.Load(request.Id);
    if (carGroup != null && carGroup.Delete())
    {
        return new HttpResult(System.Net.HttpStatusCode.NoContent, "Car Group deleted");
    }
    return new HttpResult(System.Net.HttpStatusCode.NotFound, "Car Group not found");
}

We have created all the operations and their associated requests. Now we have to register our web service.

We start by creating an AppHost for our service that inherits from ServiceStack.WebHost.Endpoints.AppHostBase where we can configure our service if we need to, I will use the default configuration:

public class CarGroupAppHost : AppHostBase
{
    //Tell Service Stack the name of your application and where to find your web services
    public CarGroupAppHost() : base("CarGroup Web Services", typeof(CarGroupService).Assembly) { }

    public override void Configure(Container container)
    {
        Routes
            .Add<CarGroup>("/carGroup", "POST")
            .Add<CarGroup>("/carGroup", "PUT");
    }
}

We have added the route configuration for our create (POST) and update (PUT) operations.

Now in the Global.asax.cs file (you need to create it if it does not exist) we initialize our service host:

public class Global : System.Web.HttpApplication
{

    protected void Application_Start(object sender, EventArgs e)
    {
        new CarGroupAppHost().Init();
    }
}

We can found some information about our operations on the url ‘http://server/metadata’, in my case http://localhost:4305/metadata.

Service metadata information

Service metadata information



And that is all, we can test now our service, we will use a Console application.

For example to retrieve all our Car Groups:

string uri = "http://localhost:4305/carGroup";
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Accept = "application/json";//we only accept JSON
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    Console.WriteLine(response.StatusCode);
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        string result = reader.ReadToEnd();
        Console.WriteLine(result);
    }
}

And we get:

Get all data service result

Get all data service result



Let’s now test the creation of a new CarGroup:

string uri = "http://localhost:4305/carGroup";
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Accept = "application/json"; //we only accept JSON
request.Method = "POST";
request.ContentType = "application/json; charset=UTF-8";//we will send JSON

string bodyData = "{\"Name\":\"Super Sport\",\"Category\":\"Mega Sport\"}";

//----- writing data in to the request --------------
request.ContentLength = bodyData.Length;
using (StreamWriter requestWritter = new StreamWriter(request.GetRequestStream()))
{
    requestWritter.Write(bodyData);
}

//----- reading the response
string result = "";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    Console.WriteLine(response.StatusCode);
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        result = reader.ReadToEnd();
        Console.WriteLine(result);
    }
}

We have just seen how CodeFluent Entities can be easily integrated to ServiceStack.

ServiceStack is a very powerful framework to write Web APIs, you can find more information about ServiceStack and all the features it provides here.

Regards.

Pablo Fernandez Duran

Get started with the CodeFluent Entities API

March 6, 2013 Leave a comment

The CodeFluent Entities API has been around for a while, and this post will help you get started with it! If I tell you that the API is very easy to use and extremely powerful, you will not believe me. Hopefully, you will believe me by the end of this post.

We assume that we have a CodeFluent Entities solution, with its CodeFluent project and its class library for the BOM. We also have created an empty console application.

In this console application, we need to reference 3 libraries:

  • CodeFluent.Model
  • CodeFluent.Model.Common
  • CodeFluent.Runtime

We are now ready to write some code. First we need to load the CodeFluent model, which is a cfp file. This cfp file is an XML file that corresponds to our CodeFluent Entities model:

Project project = new Project();
project.Load(@"c:\path\to\model\myModel.cfp");

The next step is to navigate through the model, and this is where things get easier!

foreach (Entity e in project.Entities)
{
    Console.WriteLine("Entity: " + e.Name);
    foreach (Property p in e.Properties)
    {
        Console.WriteLine(" |- Property: " + p.Name);
        // insert code below here
    }
}

If this code does not try to edit the model, it shows you that the API is very straight forward. In a few lines, the API lets you navigate through every property of every entity of your ALL model! And yes, you can also read every attribute of each property, read the methods, rules…

Now, let us try to modify the model. We will look at the default value of each property, and modify some of them:

if (!string.IsNullOrEmpty(p.DefaultValue))
{
    switch (p.DefaultValue)
    {
        case "MyDefaultTitle":
            Console.Write("DEFAULT VALUE: " + p.DefaultValue + " was changed to: ");
            p.DefaultValue = "Title";
            Console.Write(p.DefaultValue + Environment.NewLine);
            break;
        case "Sample2":
            Console.Write("DEFAULT VALUE: " + p.DefaultValue + " was changed to: ");
            p.DefaultValue = "Sample1";
            Console.Write(p.DefaultValue + Environment.NewLine);
            break;
        case "Sample1":
            Console.Write("DEFAULT VALUE: " + p.DefaultValue + " was changed to: ");
            p.DefaultValue = "Sample2";
            Console.Write(p.DefaultValue + Environment.NewLine);
            break;
    }
}

We are looking for three default values (“MyDefaultTitle”, “Sample1″, “Sample2″) and we are modifying them. There is one last thing to do, which is to save the model.

project.Package.Save();

The save method needs to be inserted at the end of your method, outside the for loops.

In this example, you have learned how to use the API to modify your CodeFluent Entities model. To go further, you could add/edit/delete methods, rules, producers… The possibilities are almost limitless and yet, the API remains very easy to use. Have fun!

Vincent Patry

Using ASP .NET Web API with CodeFluent Entities

February 27, 2013 2 comments

This post will guide you in implementing a service layer over HTTP using ASP .NET Wet API and CodeFluent Entities.

WCF is great to expose SOAP based web services and even JSON services. However WCF does not capitalize all the possibilities that the HTTP protocol can provide.

Indeed, HTTP is a real application-level protocol, and while WCF uses HTTP only as a transport protocol (as could be TCP, UDP, named Pipes…) the ASP .NET Web API takes advantage of all the features that the HTTP protocol provides as:

  • Actions defined by verbs: GET, POST, PUT, DELETE.
  • Headers that can suggest extra information like caching, requested content, security.
  • A body that can be used for any kind of content (not only XML like for SOAP web services).
  • URIs that can be used for identify resources and actions.

For this post we will use the CodeFluent Entities demo project ‘CarRental’.

Car Rental Demo Project

Car Rental Demo Project

And we are going to add a Persistence producer (SQL Server 2012 for me), a Business Object Model (BOM) producer and a Service sub producer so we can use the WCF serialization.

Producers

Producers

We will host our services in an ASP .NET MVC 4 web site (ASP .NET Web API can also be hosted as a service), more information here.

MVC 4 Internet Application

MVC 4 Internet Application

The ASP .NET Web API provides a custom ‘Controller’ that handles the HTTP actions (GET, POST, PUT, and DELETE) as well as the content negotiation (XML, JSON, HTML…), this base controller is of type System.Web.Http.ApiController.

As the HTTP services are resource-oriented services we may want to create one Controller per Entity in our model. We will lead this post using only the Entity ‘CarGroup’ of our model. We can create some instances of type CarGroup to have some data to test.

So we first need to create a controller that extends from ‘ApiController’. We will call it ‘CarGroupController’.

CarGroupController

CarGroupController

We can see in the code of our new Controller that some methods have been created. These methods will be associated with the HTTP actions (verbs) GET, POST, PUT and DELETE.

CarGroupController Acitons

CarGroupController Acitons

Besides, adding an Api Controller made a route configuration specific to ASP .NET Web API (App_Start->WebApiConfig.cs), so the routes for our resources will be {base url}/api/{controller}/{id}. For example, we will have http://localhost:21020/api/cargroup.

ASP .NET Web API uses a ‘Convention over Configuration’ approach so the prefix of each method matches a specific HTTP action.

We are now going to implement the Actions.

To get all the instances of type CarGroup :

// GET api/cargroup
public IEnumerable<CarGroup> Get()
{
    return CarGroupCollection.LoadAll();
}

To get one CarGroup by Id:

// GET api/cargroup/5
public CarGroup Get(int id)
{
    CarGroup carGroup = CarGroup.Load(id);
    if (carGroup == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return carGroup;
}

To create a new CarGroup :

// POST api/cargroup
public HttpResponseMessage Post([FromBody]CarGroup carGroup)
{
    if (carGroup == null || !carGroup.Save())
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
    return Request.CreateResponse(HttpStatusCode.OK, carGroup);
}

To update a CarGroup :

// PUT api/cargroup
public HttpResponseMessage Put([FromBody]CarGroup carGroup)
{
    if (carGroup == null || !carGroup.Save())
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
    return Request.CreateResponse(HttpStatusCode.OK, carGroup);
}

And finally to delete a CarGroup :

// DELETE api/cargroup/5
public HttpResponseMessage Delete(int id)
{
    CarGroup carGroup = CarGroup.Load(id);
    if (carGroup != null && carGroup.Delete())
    {
        return Request.CreateResponse(HttpStatusCode.NoContent);
    }
    return Request.CreateResponse(HttpStatusCode.NotFound);
}

As you can see, we have easily created a Controller able to support CRUD operations. The ASP .NET Web API will manage all the aspects like content negotiation and HTTP verbs (GET, POST, PUT and DELETE).

As we have added a Service Sub Producer to our model, we can use the data contract serialization (System.Runtime.Serialization.DataContractSerializer).

Let us test our Web API Controller, we will use a simple Console Application.

For example to retrieve all our Car Groups:

string uri = "http://localhost:21020/api/cargroup";
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Accept = "text/xml";//we only accept XML
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    Console.WriteLine(response.StatusCode);
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        string result = reader.ReadToEnd();
        Console.WriteLine(result);
    }
}

And what we get (do not forget to add some instances to your model or you will not have any data):

Web API call test

Web API call test

If you want to get a specific CarGroup (id=1 for example) we only need to modify the URL (GET method):

string uri = "http://localhost:21020/api/cargroup/1";

If we want to test our other methods we only need to set the right HTTP method (verb), the right parameters (if needed) and the body data (if needed).

For example to update a CarGroup (PUT HTTP method):

CarGroup carGroup = //retrieve a CarGroup instance
carGroup.DailyRate++;//update the instance

string uri = "http://localhost:21020/api/cargroup";
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Accept = "text/xml"; //we only accept XML
request.Method = "PUT";
request.ContentType = "text/xml; charset=UTF-8";//we will send XML
string bodyData = "";

//----- serializing data --------------
DataContractSerializer serializer = new DataContractSerializer(typeof(CarGroup));
using (MemoryStream stream = new MemoryStream())
{
    serializer.WriteObject(stream, carGroup);
    stream.Seek(0, SeekOrigin.Begin);
    using (StreamReader reader = new StreamReader(stream))
    {
        bodyData = reader.ReadToEnd();
    }
}
//----- writing data in to the request --------------
request.ContentLength = bodyData.Length;
using (StreamWriter requestWritter = new StreamWriter(request.GetRequestStream()))
{
    requestWritter.Write(bodyData);
}

//----- reading the response
string result = "";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    Console.WriteLine(response.StatusCode);
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        result = reader.ReadToEnd();
    }
}

//----- deserializing the response
CarGroup updatedObject = null;
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(result)))
{
    updatedObject = (CarGroup)serializer.ReadObject(stream);
}

This works great with XML, and if we want to use JSON we only need to specify it in our request.

request.Accept = "text/json"; //we only accept JSON
request.ContentType = "text/json; charset=UTF-8";//we will send JSON

We can even send XML and ask for JSON or send JSON and ask for XML.

We need to tell ASP .NET Web API to use the WCF JSON serializer.

In the App_Start->WebApiConfig.cs file:

JsonMediaTypeFormatter jsonFormatter = (JsonMediaTypeFormatter)config.Formatters.FirstOrDefault(f => f is JsonMediaTypeFormatter);
if (jsonFormatter != null)
{
    jsonFormatter.UseDataContractJsonSerializer = true; // use WCF serializer
}

More about serialization for ASP .NET Web API here.

Well, we have manually built an Api Controller for one entity in our model. It will be great to create automatically an Api Controller for each one of our entities.

We can achieve this by making a Template, but this will be your “homeworkSmile.

You can find some information in building templates here or here.

Regards.

Pablo Fernandez Duran

Website Templates and Custom Renderers

December 4, 2012 Leave a comment

There are basically two ways to customize web sites generated by CodeFluent Entities:

1) edit the generated files in place. The generated code is very readable, and by design easy to customize.
2) modify how the out-of-the-box site is generated. Please note these auto-generated sites are very well suited for back-end/back-office/administration/testing/sample purpose. However, they are generated using site templates, and these templates can be customized. We will try to explain how.

Site templates are located in \Program Files (x86)\SoftFluent\CodeFluent\Modeler\Templates\UI. Here you will find the various templates for ASP.NET, MVC, Ajax, etc…

These templates are a good start to build your own. Each template is composed of two directories:

    • A directory that contains a cf_template.xml which is the template manifest, used by tools such as Visual Studio. Let’s say it’s named ‘MyAspNet’ for our example.
    • Another directory named [directoryName]_Renderers. So it should be named MyAspNet_Renderers for our example.

Both directories can contain template files (text files with the .tpl extension) or any other files. Template files are files that are executable files and can run in the context of the model being produced (more here:http://www.softfluent.co…_TheTemplateEngine.html and here: http://www.softfluent.co…s_TemplateProducer.html).

The first directory will define the target site files. The renderers directory will contains the renderers implementation. Now the question: what is a renderer?

A renderer in a CodeFluent Entities model is an abstract platform-independent item which basically has two important properties: a name, and a type (unspecified, read, write, create, column, parameter), and will be used to define how a concept will be rendered ultimately on a specific platform (whatever that platform will be: web, winforms, WPF, etc.).
Renderers can be associated with properties, view properties, entities or method parameters. Renderers can be shared.

For example, let’s suppose you handle a lot of IP Address in your application. There’s nothing built-in in the product but many entities have properties that are of the IP Address type. Then, you would declare a renderer named ‘IPAddress’ (for example) and associate this renderer to all the properties of that type.
At production time, a producer such as the ASP.NET producer will relate the renderer definition to a concrete UI artifact using it’s name and type. In the case of the ASP.NET producer, a renderer will be simply represented by a file, containing some HTML (or ASP.NET) fragment. You can see what the out-of-the-box renderers look like if you open the files in the [directory]_Renderers directory of the out-of-the-box templates. A renderer file name starts with “Renderer.”.

Let’s go to CodeFluent Entities installation directory, and navigate through the Templates\UI directory. Here you can see a set of folders containing the templates and renderer.

We’re going to create a new template from an existing one and also add a renderer. To do so copy the following folders to a folder called “UI” in the location of your choice (Note the folder root must contain ‘UI’):

  • AspNet
  • AspNet_Renderers
  • AspNetWebForms
  • AspNetWebForms_Renderers

Rename the last two copied folders like this:

  • CustomWebsite
  • CustomWebsite_Renderers
    You should have something like this:

image

We We copied two website templates because the AspNetWebForms template inherits the AspNet template.

You can already customize your website here. For instance edit CustomWebsite\Default.aspx.tpl, and modify the page title by modifying the
<%@ Page %> tag with something like this:

<%@ Page Title=”This is my Custom Website Home Page” …

Now add a new file called Renderer.MyContactSource.tpl in the CustomWebsite_Renderers folder. Open this file in a text editor such as NotePad and type the following text: “this is my custom Contact Source”. It is an unspecified renderer because the file name does not end with Write, or Column for example.

image

Now start Visual Studio, and create a CodeFluent Entities project (Demo.ContactManager, C#, SQL Server, ASP.NET WebForms). Go in the Contact Entity, select the ContactSource property and add a ‘MyContactSource’ renderer of unspecified type:

Now, double-click on the ASP.NET Webforms producer, and configure it to point to your custom site template:

Build the project, and execute the generated web site. You should now see this when you try to Add or Edit a new Contact:

what happened is, at generation time, every time a property is associated with the MyContactSource renderer, it will be rendered using the content of the Renderer.MyContactSource.tpl file. This file just contain a pure (HTML) text, but it could contain anything you would like, including server-side ASP.NET controls. This file can also contain template code so you can indeed have it vary using the model and the source object it was instantiated from at generation time.
For example, if you don’t like the drop down list that’s used to represent relations by default, you can just modify the Renderer.Relation.Write.tpl content and this will change how relations are rendered (in write mode) in every screen of the application, because Relation is the name of the default renderer associated with M:0/1 or 0/1:M relations. Association is the name of the default renderer associated with M:N relations.

Besides, navigate back to the homepage and note that Tab’s title reflects our change made in the Default.aspx file.

Therefore, thanks to Renderers and custom templates you can generate full customized websites.

Cheers

User Interfaces generated by CodeFluent Entities using out-of-the-box producers

October 16, 2012 2 comments

Over the past articles we showed you how to use the following UI producers provided out of the box by CodeFluent Entities:

· Windows Store producer

· ASP.NET Web Forms Producer / AJAX/JSON

· WPF Smart Client Producer

· SharePoint Web Part Producer

In this article I want to emphasize the fact that CodeFluent Entities is totally UI-agnostic. Indeed from the same and unique model you can generate screens that will be rendered in the targeted platforms of your choice. Here is for instance the list of all UI producers available:

UI_Producer

Let see all the user interfaces that CodeFluent Entities has been able to generate from the exact same model, using those different producers.

Note that the generated applications are not just a set of user interfaces; they are actually complete interactive applications sharing the same business object model, database and are 100% functional.

We used the “ContactManager Sample Model” supply by CodeFluent Entities:

ContactManagerModel

Here is the ContactManager model:

ContactManagerSurface

Since we’ve already seen how to use the producers provided by CodeFluent Entities in previous blog posts I’m going to skip their configurations and directly present you the generated UIs:

UI generated using the Windows 8 Store Producer:

The homepage generated by default lists all namespaces and their contained entities:

Windows Store (1)

Clicking on an entity gets you to the entity page.
On this entity page you’ll find a screenshot of the entity from which this page was generated.

Right Clicking on this page or typing Ctrl+Z will bring up a menu at the bottom where you’ll find the list of actions available on this entity. Those actions correspond in fact to business methods provided by the entity:

Windows Store (2)

Here is the screen displaying for the Contact entity when clicking on the “LoadAll” button and then selecting a contact:

Windows Store (3)

Bringing back the menu by hitting Ctrl+z or right clicking will enable you to create, edit or delete an entry:

Windows Store (4)

For instance, pushing the Edit button will give you the following screen:

Windows Store (5)

UI generated using the ASP .NET MVC Producer:

The homepage generated by default lists all namespaces and their contained entities:

ASP NET WebApp (1)

Clicking on an entity gets you to the entity page.
On this entity page you’ll find a screenshot of the entity from which this page was generated.

On the left side of the page you’ll find a list of actions available on this entity. Those actions correspond to business methods provided by the entity:

ASP NET WebApp (2)

Here is the screen displaying for the Contact entity when clicking on the “LoadAll” button:
It lists all the contacts through an HTML table and enables sorting.
From it you can detail, edit or remove a contact.

ASP NET WebApp (3)

Clicking on the “Details” hyperlink will bring up the following screen:

ASP NET WebApp (4)

Clicking on the “Edit” hyperlink will enable you to edit the entry:

ASP NET WebApp (5)

UI generated using the ASP .NET AJAX Producer:

The homepage generated by default lists all namespaces and their contained entities:

ASP NET AJAX-JSON (1)

Clicking on an entity gets you to the entity page.
On this entity page you’ll find a screenshot of the entity from which this page was generated.

On the left side of the page you’ll find a list of actions available on this entity. Those actions correspond to business methods provided by the entity:

ASP NET AJAX-JSON (2)

Here is the screen displaying for the Contact entity when clicking on the “LoadAll” button:
It lists all the contacts through an Ajax grid supporting sorting and paging.
From it you can detail, edit or remove a contact.

ASP NET AJAX-JSON (3)

And the one when clicking on the “Edit” button:

ASP NET AJAX-JSON (4)

UI generated using the ASP .NET WebForms Producer:

The homepage generated by default lists all namespaces and their contained entities:

ASP NET WebForms (1)

Clicking on an entity gets you to the entity page.
On this entity page you’ll find a screenshot of the entity from which this page was generated.

On the left side of the page you’ll find a list of actions available on this entity. Those actions correspond to business methods provided by the entity:

ASP NET WebForms (2)

Here is the screen displaying for the Contact entity when clicking on the “LoadAll” button:
It lists all the contacts through an HTML table and enables sorting.
From it you can edit or remove a contact.

ASP NET WebForms (3)

And the one when clicking on the “Edit” button:

ASP NET WebForms (4)

UI generated using the Smart Client (WPF) Producer:

The first screen generated by default lists all namespaces and their contained entities:

SmartClient (1)

Clicking on an entity will load all the data corresponding to it:
From it you can create, edit or remove an entry.

SmartClient (2)

Clicking on an entry will open a window to edit it:

SmartClient (3)

UI generated using the SharePoint WebParts Producer:

The homepage generated by default lists all namespaces:

SharePoint (1)

Clicking on a namespace lists all its entities:

SharePoint (2)

Clicking on an entity gets you to the entity page:
It lists all the data of that entity through a Web Part.
From it you can create a new entry, detail, edit or delete one.
SharePoint (3)

For instance, clicking on an entry brings up its details:

SharePoint (4)

and clicking on the “Edit” button brings up the editor:

SharePoint (5)

As you can see, from a same model we have generated several UIs all consistent with each other.

Besides, thanks to the Platform Independent Form Editor you can also define forms directly on their entities which will then be translated into actual screens by user interface producers. We talked about it in details in this article.

Finally, in the case you did not find the desired producer, I remind you that you can create your own template and use it with the Template Producer or you can even create your own custom producer. All you’ll need to do would be to implement the IProducer interface.

To sum up, CodeFluent Entities is able to generate 100% functional applications with the UI of your choice just by using the right producer.

Cheers,

Thibault Nestor

Follow

Get every new post delivered to your Inbox.

Join 41 other followers