Dictionary Lookup Web Service

by Chris 10. July 2009 12:28

It's time to continue my series (I Want More Mobile (Web) Services and Flight Lookup Web Service, Package Lookup Web Service, and Movie Lookup Web Service) of useful Web Services for Windows Mobile with a service to look up definitions of words in a dictionary. I sometimes want to get the definition of a word that I've stumbled on, and since I'm often in a discussion or reading something when this happens, I want to do it wherever I am at that moment. Since a good dictionary is extensive (also regularly updated) and therefore not very suitable to install/store on a mobile device, a simple client to a web service would be a nice solution. As for the other Web Services in this series, you can get the code on CodePlex in a project called Windows Mobile Web Services.

dictlookup As in previous posts, you find the UX on the right, and this is the code behind the right menu button (somewhat simplified)...

WebServices.Service ws = new WebServices.Service();
definitionTextBox.Text = ws.DictionaryLookup(wordTextBox.Text).Replace("\n", "\r\n");

...so when a word is entered in the text box, the following code on the server is run...

[WebMethod]
public string DictionaryLookup(string word)
{
   
const string host = "www.dict.org";
   
const int port = 2628;
   
const string database = "wn";

   
// Connect to dictionary (RFC 2229) server
    TcpClient tc = new TcpClient(host, port);
   
StreamReader sr = new StreamReader(tc.GetStream());
   
DictServerStatus status = new DictServerStatus(sr.ReadLine());
   
if(status.Code != (int)DictServerStatusCodes.Banner)
       
throw new Exception(status.ToString());

   
// Send command (DEFINE)
    string command = string.Format("DEFINE \"{0}\" \"{1}\"\r\n", database, word);
   
Encoding enc = System.Text.Encoding.ASCII;
    tc.GetStream().Write(enc.GetBytes(command), 0, enc.GetBytes(command).Length);

   
// Get definition(s) for word
    status = new DictServerStatus(sr.ReadLine());
   
if(status.Code != (int)DictServerStatusCodes.Definitions)
       
throw new Exception(status.ToString());

   
// Parse definitions
    int definitionCount = Convert.ToInt32(status.Message.Substring(0,
        status.Message.IndexOf(" ") + 1));
   
Hashtable definitions = new Hashtable(definitionCount);
   
for(int i = 0; i < definitionCount; i++)
    {
        status =
new DictServerStatus(sr.ReadLine());
       
if(status.Code == (int)DictServerStatusCodes.Definition)
        {
           
string responseText = string.Empty;
           
string s = sr.ReadLine();
           
while(s != ".")
            {
                responseText += s +
"\r\n";
                s = sr.ReadLine();
            }
           
Match definitionLine = Regex.Match(status.Message, "^\\\"(?<word>[^\\\"]+)\\\"\\s+(?<database>[\\S]+)\\s+\\\"(?<dbname>[^\\\"]+)\\\"$");
            definitions.Add(definitionLine.Groups[
"database"].ToString(),
                responseText);
        }
       
else
            throw new Exception(status.ToString());
    }
   
string definition = string.Empty;
    status =
new DictServerStatus(sr.ReadLine());
   
if(status.Code == (int)DictServerStatusCodes.Ok)
        definition = definitions[database].ToString();
   
else
        throw new Exception(status.ToString());

   
return definition;
}

...and in contrast to the previous posts in this series, this Web Service isn't using "scraping" to get the info from a Web page. Instead, the method used to access the dictionary is the standard Dictionary Server Protocol (RFC 2229). It's a text-based protocol (not HTTP, so plain sockets are used) that defines a range of dictionary functionality, and the above code is just using the ability to lookup (command DEFINE) a word in a dictionary.

The dictionary used is the WordNet database located at the DICT Development Group site.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Chris | Compact Framework | WM Web Services

KISS Architecture (part 10)

by Chris 30. January 2009 16:16

KISS Architecture Mobile Sample This is the final post in this series, and for a complete reference, here are the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)
  • Part 4 started the implementation by creating the entity data model (using ADO.NET Entity Framework)
  • Part 5 published the entity data model as a data service (using ADO.NET Data Services)
  • Part 6 implemented the business domain (using the data service)
  • Part 7 created the service (using WCF)
  • Part 8 started the implementation of the mobile client (using WCF)
  • Part 9 added offline support to the mobile client (using SQL Server Compact, etc)

The implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc.

On the upper right you see the UX of the sample client included in the architecture sample, and the functionality is that a part of a city name can be entered in the text box, and when the "Get" menu item is selected, the grid is filled with the matching customers.

Even if this series is complete, I will continue to build further on this architecture blueprint, and any suggestions on things to add are most welcome. Any other feedback, for that matter, is also welcome!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Architecture | Chris | Compact Framework | Windows Mobile

KISS Architecture (part 9)

by Chris 23. January 2009 16:11

In this part, I will continue the implementation of the presentation tier for Windows Mobile, and if you want some background, please see the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)
  • Part 4 started the implementation by creating the entity data model (using ADO.NET Entity Framework)
  • Part 5 published the entity data model as a data service (using ADO.NET Data Services)
  • Part 6 implemented the business domain (using the data service)
  • Part 7 created the service (using WCF)
  • Part 8 started the implementation of the mobile client (using WCF)
  • The implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, I suggest you keep the source code handy to check out more details.

    In the previous part (8) of this blog series, I showed how the Windows Mobile client can call a WCF service when connected to the network. However, there are a number of times when the mobile device is not connected and still need to allow the application to function. It would be really awesome if the new technologies like ADO.NET Data Services, ADO.NET Entity Framework, LINQ to Entities, etc, were available also for Windows Mobile and .NET Compact Framework, as this would mean that we could use identical code (assemblies/tiers) on the client, but unfortunately they are not (yet).

    So, what is the second best solution? I still want to make use of the entities defined by the (data) service tier, and not maintain any custom entity code. Also, I want the implementation to be as simple as possible (remember the KISS principle) and make it as easy as possible to upgrade when these new technologies are available. That means that I don't want to spend time writing my own custom framework, but rather something simple that just works.

    To allow local data storage, I create a SQL Server Compact database by adding a "Database File" named Northwind.sdf to the Kiss.Mobile project. To that database, I then add the same tables that our order (data) service defines (see part 4 of this blog series). I also add a plain class named Common.cs to the same project that is a singleton holding a single connection to the database.

    With the local database in place and a connection to it, the code for the "Get" menu item can be changed into:

    private void getMenuItem_Click(object sender, EventArgs e)
    {
       
    Customer[] customers;
       
    if(online)
        {
           
    OrderServiceClient.EndpointAddress = new EndpointAddress("http://192.168.0.100:2222/OrderService.svc");
           
    OrderServiceClient service = new OrderServiceClient();
            customers = service.GetCustomersByCity(cityTextBox.Text);
        }
       
    else
        {
           
    OrderHandler data = new OrderHandler();
            customers = data.GetCustomersByCity(cityTextBox.Text);
        }
        dataGrid.DataSource = customers;
    }

    The variable indicating connection state (online) can be either manual or automatic through SystemState.ConnectionsCount. Before we take a look at the OrderHandler class, here's the updated code for the "Update" menu item:

    private void updateMenuItem_Click(object sender, EventArgs e)
    {
       
    Customer customer = ((Customer[])dataGrid.DataSource)[0];
        customer.City = customer.City + "X";

       
    if(online)
        {
           
    OrderServiceClient service = new OrderServiceClient();
            service.UpdateCustomer(customer);
        }
       
    else
        {
           
    OrderHandler data = new OrderHandler();
            data.UpdateCustomer(customer);
        }
    }

    Ok, so with that in place, here's the implementation of the OrderHandler class:

    public class OrderHandler
    {
       
    public Customer[] GetCustomersByCity(string city)
        {
           
    //var q = from c in data.CustomerSet
            //        where c.City.Contains(city)
            //        select c;
            return HandlerHelper.GetObjects<Customer>(string.Format(
               
    "SELECT * FROM Customers WHERE City LIKE '%{0}%'", city));
        }

       
    public void UpdateCustomer(Customer customer)
        {
           
    HandlerHelper.UpdateObject<Customer>(customer, string.Format(
               
    "SELECT * FROM Customers WHERE CustomerID='{0}'", customer.CustomerID));
        }
    }

    Not much happening here except that the handler make use of a helper that I wrote to take care of the plumbing. I can use the entity type and I need to define the query as plain SQL, but note that I've kept the desired LINQ as a comment in preparation for the day when it can be used. Let's look at the implementation of the helper class:

    public static class HandlerHelper
    {
       
    public static T[] GetObjects<T>(string sql) where T : new()
        {
           
    List<T> objects = new List<T>();
           
    SqlCeCommand command = Common.Values.DatabaseConnection.CreateCommand();
            command.CommandText = sql;
           
    SqlCeDataReader reader = command.ExecuteReader();
           
    Type type = typeof(T);
           
    while(reader.Read())
            {
                T entity =
    new T();
               
    for(int i = 0; i < reader.FieldCount; i++)
                {
                    PropertyInfo propertyInfo = type.GetProperty(reader.GetName(i));
                    propertyInfo.SetValue(entity, reader[i],
    null);
                }
                objects.Add(entity);
            }
           
    return objects.ToArray();
        }

       
    public static void UpdateObject<T>(T entity, string sql)
        {
           
    SqlCeCommand command = Common.Values.DatabaseConnection.CreateCommand();
            command.CommandText = sql;
           
    SqlCeResultSet resultSet = command.ExecuteResultSet(ResultSetOptions.Updatable);
            resultSet.Read();
           
    Type type = typeof(T);
           
    for(int i = 0; i < resultSet.FieldCount; i++)
            {
               
    PropertyInfo propertyInfo = type.GetProperty(resultSet.GetName(i));
               
    object value = propertyInfo.GetValue(entity, null);
                if(!value.Equals(resultSet.GetValue(i)))
                    resultSet.SetValue(i, value);
            }
            resultSet.Update();
        }
    }

    The database connection kept by the singleton (Common.Values) is used to either query or update the local database. Both methods are implemented using generics, and reflection is used to find all the attributes (fields). To optimize performance, a data reader is used for the query and a resultset is used for the update. Both methods are somewhat simplified as some extra null handling is necessary but does not add to the discussion. Using reflection is not an ideal solution, but remember that my goal is to keep the implementation as simple as possible and also that this is not a solution for the future, it's a temporary fix in the lack of the right technologies on the device. When that day comes, the helper class can be scrapped, and the handler class either updated or even replaced by something like LINQ to Entities.

    In the next part, I will conclude this series.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    KISS Architecture (part 8)

    by Chris 16. January 2009 16:09

    In this part, I will start the implementation of the presentation tier for Windows Mobile, and if you want some background, please see the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)
  • Part 4 started the implementation by creating the entity data model (using ADO.NET Entity Framework)
  • Part 5 published the entity data model as a data service (using ADO.NET Data Services)
  • Part 6 implemented the business domain (using the data service)
  • Part 7 created the service (using WCF)
  • The implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, I suggest you keep the source code handy to check out more details.

    kisswmform

    I start the implementation of a Windows Mobile client by creating a new project of type "Smart Device Project", name it Kiss.Mobile, select "Windows Mobile 5.0 Smartphone SDK", ".NET Compact Framework Version 3.5", and "Device Application". This will allow it to run on many of the devices on the market, and still use the latest framework with new functionality. That new functionality include WCF, so let's move on by creating a reference to the WCF service I created in the previous part (7). You do that by using the tool NetCFSvcUtil that is included in the Power Toys for .NET Compact Framework 3.5. For more details on using this tool, please see A New Mobile N-tier Architecture (part 8).

    Let's implement a simple user interface by renaming the automatically generated form (Form1) to MainForm, and add three controls (a Label named cityLabel, a TextBox named cityTextBox, and a DataGrid named simply dataGrid) to it. Also, add a MainMenu named mainMenu and add menu options to it named doneMenuItem, getMenuItem, and updateMenuItem. The result should look similar to the figure on the left.

    With the service reference and the user interface in place, it's time to implement some presentation logic. Here's the code for the "Get" menu item:

    private void getMenuItem_Click(object sender, EventArgs e)
    {
        OrderServiceClient.EndpointAddress = new EndpointAddress("http://192.168.0.100:2222/OrderService.svc");
       
    OrderServiceClient service = new OrderServiceClient();
        Customer[] customers = service.GetCustomersByCity(cityTextBox.Text);
        dataGrid.DataSource = customers;
    }

    Note how easy it would be to redirect the client to use the service in another location (other server, cloud, etc) by just changing the service URI. Also note how the definition of the entity (Customer) have come all the way from the data service without any manual coding anywhere, and when it is changed, it's simply a matter of updating the service references in all tiers. The observant will note that the List<Customer> return value of the service is transformed into a plain array when serialized by WCF, but if a list is preferred, this code could be used:

    List<Customer> customers = service.GetCustomersByCity(cityTextBox.Text).ToList();

    The code for the "Update" menu item looks like this:

    private void updateMenuItem_Click(object sender, EventArgs e)
    {
       
    Customer customer = ((Customer[])dataGrid.DataSource)[0];
        customer.City = customer.City + "X";
        OrderServiceClient service = new OrderServiceClient();
        service.UpdateCustomer(customer);
    }

    It first takes the first row in the grid, and adds an "X" to the City attribute. Then the service is called with the updated entity instance (customer). It can't be much simpler than this!

    In the next part, I will continue the implementation of the Windows Mobile client by adding offline support.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    KISS Architecture (part 7)

    by Chris 9. January 2009 16:07

    In this part, I will continue the implementation of the middle tier by publishing a WCF service, and if you want some background, please see the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)
  • Part 4 started the implementation by creating the entity data model (using ADO.NET Entity Framework)
  • Part 5 published the entity data model as a data service (using ADO.NET Data Services)
  • Part 6 implemented the business domain (using the data service)
  • The implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, I suggest you keep the source code handy to check out more details.

    It's time to create the service, and I do that by creating a new project of type "WCF Service Application" and name it Kiss.Service. First I add a reference to the Kiss.Domain project, and then I rename the automatically generated interface to IOrderService.cs. I change its code to...

    namespace Kiss.Service
    {
        [
    ServiceContract]
       
    public interface IOrderService
        {
            [
    OperationContract]
           
    List<Customer> GetCustomersByCity(string city);

            [
    OperationContract]
           
    Customer GetCustomer(string id);

            [
    OperationContract]
           
    void UpdateCustomer(Customer customer);
        }
    }

    ...and make sure all references to it is refactored (there are a number of places, like in the Web.config file). Then I rename the generated service class to OrderService.cs and update its (references and) code to:

    namespace Kiss.Service
    {
        [
    AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
       
    public class OrderService : IOrderService
        {
           
    private OrderDomain orderDomain = new OrderDomain();

           
    public List<Customer> GetCustomersByCity(string city)
            {
               
    return orderDomain.GetCustomersByCity(city);
            }

           
    public Customer GetCustomer(string id)
            {
               
    return orderDomain.GetCustomer(id);
            }

           
    public void UpdateCustomer(Customer customer)
            {
                orderDomain.UpdateCustomer(customer);
            }
        }
    }

    This is the actual implementation of the service that implement the interface mentioned above, and each method simply use the domain class to do its work. The decoration (attribute) of the service class is needed to make the service available for a Silverlight 2 client. Even if no such client exist for Windows Mobile yet, this is a good measure to prepare for the future.

    Another similar measure is to include two more files in the service project, and the first is clientaccesspolicy.xml and the second is crossdomain.xml. The purpose of these files is to make the service available for applications that make cross domain calls, and the first is specific to Silverlight and the second is used by Flash applications, among others. Here is a sample clientaccesspolicy.xml file...

    <?xml version="1.0" encoding="utf-8" ?>
    <
    access-policy>
        <
    cross-domain-access>
            <
    policy>
                <
    allow-from http-request-headers="*">
                    <
    domain uri="*" />
                </
    allow-from>
                <
    grant-to>
                    <
    resource path="/" include-subpaths="true" />
                </
    grant-to>
            </
    policy>
        </
    cross-domain-access>
    </
    access-policy>

    ...that allow any client to access the service. A final measure that is necessary for both Silverlight and Windows Mobile WCF clients is to make sure that the service use the basicHttpBinding, and here is an extract of the Web.config file:

    <system.serviceModel>
        <
    services>
            <
    service behaviorConfiguration="Kiss.Service.OrderServiceBehavior" name="Kiss.Service.OrderService">
                <
    endpoint address="" binding="basicHttpBinding" contract="Kiss.Service.IOrderService">

    In the next part, I will start implementing the Windows Mobile client.

    Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    KISS Architecture (part 6)

    by Chris 2. January 2009 16:05

    In this part, I will start the implementation of the middle tier, and if you want some background, please see the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)
  • Part 4 started the implementation by creating the entity data model (using ADO.NET Entity Framework)
  • Part 5 published the entity data model as a data service (using ADO.NET Data Services)
  • The implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, I suggest you keep the source code handy to check out more details.

    With the data tier in place, I'm ready to create the middle tier, and I start by creating a plain class library named Kiss.Domain which will hold my business domain classes. I add a service reference to the data service created in the previous part (5) of this blog series, and get the complete entity data model through the generated proxy class. Then I create a plain class named OrderDomain.cs and add the following code to it:

    namespace Kiss.Domain
    {
       
    public class OrderDomain
        {
           
    OrderEntities data = new OrderEntities(new Uri("http://localhost:1111/OrderDataService.svc"));

           
    public List<Customer> GetCustomersByCity(string city)
            {
               
    var q = from c in data.CustomerSet
                       
    where c.City.Contains(city)
                       
    select c;

               
    return q.ToList();
            }

           
    public Customer GetCustomer(string id)
            {
               
    return data.CustomerSet.SingleOrDefault(c => c.CustomerID == id);
            }

           
    public void UpdateCustomer(Customer customer)
            {
                data.AttachTo(
    "CustomerSet", customer);
                data.UpdateObject(customer);
                data.SaveChanges();
            }
        }
    }

    It implements three common methods for getting a list of customers for a specified city, getting a specific customer by identity, and for updating a customer. Note that we in the list query method (GetCustomersByCity) can use LINQ to query the data service, and if you debug the code and check out the value of the query variable (q), you will see the actual query (REST) URI generated. LINQ is also used in the second query method (GetCustomer), but here in an alternative format (and with a lambda expression). Note also how simple the code is to update a customer using the data service. I have intentionally left out the other CRUD operations (insert and delete) as they should not be to hard to figure out, and don't add much to the architectural discussion.

    With this in place, you see how easy it would be to move the data service to another location (like the cloud), by simply changing the URI. Likewise, the switch between online (to the server or cloud) and offline (to a local data service) would be as easy. Unfortunately, as the ADO.NET Data Services is not yet available on Windows Mobile (yet), we need to accomplish something similar in another way (which I will show in a later part of this blog series).

    In the next part, I will implement the services tier.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    KISS Architecture (part 5)

    by Chris 26. December 2008 16:01

    In this part, I will continue with the implementation of the data service using ADO.NET Data Services, and if you want some background, please see the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)
  • Part 4 started the implementation by creating the entity data model (using ADO.NET Entity Framework)
  • The implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, I suggest you keep the source code handy to check out more details.

    Now it's time to publish the entity data model (OrderModel.edmx) that we created in the last part (4) of this blog series, and that is done by adding an "ADO.NET Data Service" named OrderDataService.svc to the data tier assembly, Kiss.Data. The modifications necessary to this service class is trivial, and involves specifying the type of the data model (object context, in my case OrderEntities) and making the complete model available to anyone. The resulting code looks like this:

    namespace Kiss.Data
    {
       
    public class OrderDataService : DataService<OrderEntities>
        {
           
    public static void InitializeService(IDataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule(
    "*", EntitySetRights.All);
            }
        }
    }

    Amazing as it sounds, the data tier is now ready to be used, and we can start querying the database through the newly built data service. For example, if we go to http://localhost:1111/OrderDataService.svc/CustomerSet('ALFKI'), we get the following result (somewhat simplified)...

    <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
    <
    entry xmlns="http://www.w3.org/2005/Atom">
        <
    id>http://localhost:1111/OrderDataService.svc/CustomerSet('ALFKI')</id>
        <
    title type="text" />
        <
    updated>2008-11-25T02:24:45Z</updated>
        <
    author>
            <
    name />
        </
    author>
        <
    link rel="edit" title="Customer" href="CustomerSet('ALFKI')" />
        <
    link type="application/atom+xml;type=feed" title="Orders" href="CustomerSet('ALFKI')/Orders" />
        <
    category term="Kiss.Data.Customer" />
        <
    content type="application/xml">
            <
    properties>
                <
    CustomerID>ALFKI</CustomerID>
                <
    CompanyName>Alfreds Futterkiste</CompanyName>
                <
    ContactName>Maria Anders</ContactName>
                <
    ContactTitle>Sales Representative</ContactTitle>
                <
    Address>Obere Str. 57</Address>
                <
    City>Berlin</City>
                <
    Region null="true" />
                <
    PostalCode>12209</PostalCode>
                <
    Country>Germany</Country>
                <
    Phone>030-0074321</Phone>
                <
    Fax>030-0076545</Fax>
            </
    properties>
        </
    content>
    </
    entry>

    ...and this allows us to query the complete data model through a RESTful interface. Note that you may have to turn off the automatic feed formatter included in Internet Explorer 7 to see the resulting XML (in ATOM format), and you do that by selecting Tools > Internet Options > Content > Feeds Settings, and uncheck "Turn on feed reading view".

    In the next part, I will start implementing the middle tier.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , , , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    KISS Architecture (part 4)

    by Chris 19. December 2008 15:59

    In this part, I will get more practical by showing how the first parts of this architecture looks in code, and if you want some background, please see the previous parts:

  • Part 1 was a general introduction
  • Part 2 outlined the architecture (tiers, etc)
  • Part 3 showed the benefit of loosely coupled tiers (distribution, cloud, etc)

    As I mentioned in the first part, the implemented architecture is published on CodePlex in a project called KISS Architecture, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, I suggest you keep the source code handy to check out more details.

    Ok, let's start building the architecture from the ground up! To make things really simple (remember the KISS principle), I start with an "ASP.NET Web Application" named Kiss.Data as the data tier. In that assembly I add an "ADO.NET Entity Data Model" class named OrderModel.edmx, and add the following tables from the Northwind database (renamed Customer, Order, OrderDetail, Product and Category):

    KISS Architecture Entity Model

    If we take a look at a simplified version of the generated code (in OrderModel.Designer.cs)...

    namespace Kiss.Data
    {
       
    public partial class OrderEntities : ObjectContext
        {
           
    public OrderEntities(string connectionString) :
                base(connectionString, "OrderEntities")
            {
               
    this.OnContextCreated();
            }
           
    public ObjectQuery<Customer> CustomerSet
            {
               
    get
                {
                   
    if(this._CustomerSet == null)
                       
    this._CustomerSet =
                           
    base.CreateQuery<Customer>("[CustomerSet]");
                   
    return this._CustomerSet;
                }
            }
           
    private global::System.Data.Objects.ObjectQuery<Customer> _CustomerSet;
        }

        [
    EdmEntityTypeAttribute(NamespaceName = "Kiss.Data", Name = "Customer")]
        [
    DataContractAttribute(IsReference = true)]
        [
    Serializable()]
       
    public partial class Customer : EntityObject
        {
            [
    EdmScalarPropertyAttribute(EntityKeyProperty = true, IsNullable = false)]
            [
    DataMemberAttribute()]
           
    public string CustomerID
            {
               
    get { return this._CustomerID; }
               
    set
                {
                   
    this.OnCustomerIDChanging(value);
                   
    this.ReportPropertyChanging("CustomerID");
                   
    this._CustomerID = StructuralObject.SetValidValue(value, false);
                   
    this.ReportPropertyChanged("CustomerID");
                   
    this.OnCustomerIDChanged();
                }
            }
           
    private string _CustomerID;
           
    partial void OnCustomerIDChanging(string value);
           
    partial void OnCustomerIDChanged();

    ...we see that in the model, or object context, (OrderEntities) there is a class created for each entity (Customer) and a query (set) for that entity (CustomerSet). Also note that each of the entity classes and its members has the necessary decorations (attributes) to be serialized correctly over WCF.

    In the next part, I will look at how to publish the data model as a data service.

  • Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    A New Mobile N-tier Architecture (part 10)

    by Chris 14. November 2008 15:29

    blueprintuiThis is the final post in this series, and for a complete reference, here are the previous parts:

    • Part 1 was a general introduction
    • Part 2 talked about the changes in the lower tiers (logic + data, LINQ2SQL)
    • Part 3 discussed the changes in communication (WCF)
    • Part 4 covered important stuff in the user interface (MVC)
    • Part 5 summarized the theory and outlined the new architecture
    • Part 6 started the walkthrough of the architecture code by looking at the business domain
    • Part 7 continued the code walkthrough with a look at the service (WCF)
    • Part 8 covered the consumption of the service with .NET CF
    • Part 9 showed the implementation of the user interface (MVC)

    The implemented architecture is published on CodePlex in a project called Windows Mobile Architecture Blueprint, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc.

    On the upper right you see the UX of the sample client included in the architecture blueprint, and the functionality is that the combo box is filled with the categories when the application starts. Then, when a category is selected, the product names are shown in the text box below.

    Even if this series is complete, we will continue to build further on this architecture blueprint, and any suggestions on things to add are most welcome. Any other feedback, for that matter, is also welcome!

    Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    Architecture | Chris | Compact Framework | Windows Mobile

    A New Mobile N-tier Architecture (part 9)

    by Chris 7. November 2008 15:27

    WeI will continue the more practical part of this series by showing how the new mobile architecture looks in code, and if you want some background, please see the previous parts:

    • Part 1 was a general introduction
    • Part 2 talked about the changes in the lower tiers (logic + data, LINQ2SQL)
    • Part 3 discussed the changes in communication (WCF)
    • Part 4 covered important stuff in the user interface (MVC)
    • Part 5 summarized the theory and outlined the new architecture
    • Part 6 started the walkthrough of the architecture code by looking at the business domain
    • Part 7 continued the code walkthrough with a look at the service (WCF)
    • Part 8 covered the consumption of the service with .NET CF

    The implemented architecture is published on CodePlex in a project called Windows Mobile Architecture Blueprint, and this means that you can access the full source code as well as discuss it, come with suggested improvements, etc. As I walk you through the creation of the architecture, we suggest you keep the source code handy to check out more details.

    It's time to look at how we can implement the MVC pattern in the Windows Mobile client project that we created in the previous part of this series. As we've touched on before in this series, we have built this part of the architecture on a very simple and straightforward implementation by Alex Yakhnin, that he published as a small blog series last fall (see part 1 and part 2).

    As Alex, I started with the core interfaces...

    interface IView
    {
       
    void Show();
       
    void Hide();
       
    void Close();
       
    string Text { get; set; }
    }
    interface IController
    {
       
    IView View { get; set; }
    }

    ...and then the interface for the main view (form)...

    interface IMainView : IView
    {
       
    Category SelectedCategory { get; }

       
    void SetCategories(Category[] categories);
       
    void SetProducts(string products);

       
    event EventHandler Done;
       
    event EventHandler CategorySelected;
    }

    ...which already tells us what the main form can do. It allows us to set a number of categories (to choose from, SetCategories) and it will notify when a category is selected (CategorySelected). It will also make that selected category available through a public property (SelectedCategory) and allow us to set the products for a (the selected) category (SetProducts). Finally, it will notify when the user is done with it (Done).

    The implementation of the controller for the main form looks like this...

    class MainController : IController
    {
       
    private IMainView view;
       
    private ServiceClient service;

       
    public MainController(IMainView view)
        {
            View = view;

           
    ServiceClient.EndpointAddress = new EndpointAddress("http://192.168.0.100:5610/Service.svc/basic");
            service =
    new ServiceClient();

           
    Category[] categories = service.GetCategories();
            view.SetCategories(categories);
        }

       
    private void attachView(IMainView view)
        {
           
    this.view = view;
            view.CategorySelected +=
    new EventHandler(view_CategorySelected);
            view.Done +=
    new EventHandler(view_Done);
        }

       
    void view_CategorySelected(object sender, EventArgs e)
        {
            Category category = view.SelectedCategory;
           
    string s = string.Empty;
           
    foreach(Product product in category.Products)
                s += product.ProductName +
    "\r\n";
            view.SetProducts(s);
        }

       
    void view_Done(object sender, EventArgs e)
        {
            Application.Exit();
        }

        #region IController Members
       
    public IView View
        {
           
    get { return view; }
           
    set { attachView(value as IMainView); }
        }
        #endregion
    }

    ..and upon creation, the controller saves its view, and set up the event handlers to capture event from the view. Then it make the first call to the service to get the category list which is sent to the view. When a category is selected, a string is created (I know, in a real solution it would be a StringBuilder, but this code is simpler to read) and passed to the view.

    The implementation of the main view (form) looks like this...

    public partial class MainForm : Form, IMainView
    {
        public MainForm()
        {
            InitializeComponent();
        }

        public Category SelectedCategory
        {
           
    get { return categoryComboBox.SelectedItem as Category; }
        }

        public void SetCategories(Category[] categories)
        {
           
    foreach(Category category in categories)
                categoryComboBox.Items.Add(category);
        }

       
    public void SetProducts(string products)
        {
            productsTextBox.Text = products;
        }

        public event EventHandler CategorySelected;
       
    private void categoryComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
           
    if(CategorySelected != null)
                CategorySelected(
    this, null);
        }

       
    public event EventHandler Done;
       
    private void doneMenuItem_Click(object sender, EventArgs e)
        {
           
    if(Done != null)
                Done(
    this, null);
        }
    }

    ...and here we see that the categories are loaded in a combo box which is used to determine the currently selected category, and also to raise the event when a category is selected. The products string is simply put into a text box, and a menu option is used to offer the user to exit.

    To manage (can cache) the various controllers and views, we use the following singleton class...

    class ApplicationManager
    {
       
    public static readonly ApplicationManager Instance = new ApplicationManager();
       
    private ApplicationManager() { }

       
    private Dictionary<string, IController> controllersCache;

       
    public MainForm GetMainForm()
        {
           
    if(!controllersCache.ContainsKey("Main"))
                controllersCache.Add(
    "Main", new MainController(new MainForm()));
           
    return controllersCache["Main"].View as MainForm;
        }
    }

    ...and the application is kicked off like this...

    [MTAThread]
    static void Main()
    {
       
    Application.Run(ApplicationManager.Instance.GetMainForm());
    }

    ...which concludes the walkthrough of the basic architecture! In the next post, we will summarize this series of blog posts on the architecture blueprint implementation.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: , ,

    Architecture | Chris | Compact Framework | Windows Mobile

    Powered by BlogEngine.NET 1.4.5.0
    Theme by Mads Kristensen