Archive

Posts Tagged ‘Web’

Knockoutjs and Convention Over Configuration

September 30, 2012 1 comment

I am a big fan of getting rid of as much ceremony as possible in my development life-cycle. I also really like the paradigm for rich databinding that we were able to do in XAML technologies. Here comes Knockout.js giving us the same richness of declarative data-binding. Knockout.js is very nice but still requires a bit of scaffolding to get our markup data bound correctly.

Here is a sample of standard Knockout.js markup:

<span>First Name:</span>
<input data-bind="value: firstName" /><br />
<span>Middle Name:</span>
<input data-bind="value: middleName" type="text" /><br />
<span>Last Name:</span>
<input data-bind="value: lastName" /><br />
<span>Password:</span>
<input data-bind="value: password" type="password" /><br />
<span>Is Active:</span>
<input data-bind="checked: isActive" type="checkbox" /><br />
<button data-bind="click: run">Run</button>

The following is the same markup but now using a using a simple convention:

<span>First Name:</span>
<input data-name="firstName" /><br />
<span>Middle Name:</span>
<input data-name="middleName" /><br />
<span>Last Name:</span>
<input data-name="lastName" /><br />
<span>Password:</span>
<input data-name="password" type="password" /><br />
<span>Is Active:</span>
<input data-name="isActive" type="checkbox" /><br />
<button data-name="run">Run</button>

Now, this may not seem like a very big deal but I would say that the less markup I have to write the better. One nice thing about this approach is that it will always honor data-bind markup first and only fallback to the convention when no standard binding exists.

Here is the output for the second markup:

If you notice carefully, you will see that the button is disabled. This is because the enable property is tied to the Is Active checkbox. You can see how the button is enabled when the Is Active checkbox is checked:

Finally, here is the viewmodel that we were bound to:

var ViewModel = function () {
    var self = this;

    self.firstName = ko.observable("Matthew");
    self.middleName = ko.observable("Kevin");
    self.lastName = ko.observable("Duffield");
    self.password = ko.observable("");
    self.isActive = ko.observable(false);

    self.canrun = ko.computed(function () {
        return self.isActive();
    }, self);
    self.run = function () {
        alert("You hit run!");
    };
};

As you can see, the convention basically allows us to take the value from the data-name attribute and find the corresponding Knockout observable on the viewmodel. We also have a default convention that takes the value from the data-name attribute and finds a corresponding function with the same name. The convention also pre-pends the word “can” to the value from the data-name attribute and binds the enable property of the button to a function with that name if it exists.

In the next post, I will walk you through building this custom convention binding provider for Knockout.

When it comes to browser compatibility, this is my favorite tool…

One of my biggest frustrations with developing web applications is the need to deal with old and clunky browsers. I find that one of my least favorite exercises is being forced to support browsers that aren’t what I would call modern. Well, I tried several tools to help me in this process and found that two different ones became my favorite.

One of the pains with working with these different browsers is that you either need to manually install every type you need or you need older machines that still have the version running for you.

I looked at Expression Web 4 Super Preview and found that although the interface was nice and did allow me to see some differences, it was 100% accurate as to what I would see in the real browser.  I found this interesting and frustrating at the same time.  It also only allowed me to test the various versions of Internet Explorer.

Here is a screen shot of Expression Web 4 Super Preview:

 

I do like the interface and what it tries to offer but I found that it wasn’t the best choice as far as rendering accuracy.

Which now leads me to my new best friend!  I discovered a service that allows you to use your desktop applications anywhere.  I now use Spoon.net as my first line of defense when it comes to testing across multiple versions of IE or whatever browser you may need.  Here is a screen show of their page:

Here is a screen show of what I am currently using just like above but now with the ability to run IE 7 and IE 8 side by side without performing any installations manually:

 

You can configure your own applications that you wish to access.  Here is a screen shot of some of the browsers that are provided:

 

I can launch both IE7 and IE8 side by side.  I also have IE9 as my main browser so this gives me the ability to test all three versions that I care about.

Here is what IE7 looks like when launched:

 

As you can see, this is just what you would expect from IE7.  Now let’s see IE8:

 

 

Again, no surprises here.  What I really like about this service is that I can access it from any computer and perform my testing as I need without the need to configure my computer.

It does cost a little but it is well worth the price to know that your web applications will look sharp across any browser version and more.  This service allows you to have more than just browsers to access from anywhere.

Hope this helps…

 

Building a generic serivce using WCF Web API – Part IV

December 21, 2011 1 comment

So now that we have covered building our service and testing it with Test Client. Let’s now get started and see what it takes to actually build a Silverlight client. The WCF Web API does not have code to directly support Silverlight but luckily there is another project on CodePlex that does just that. There is a fork here that has the source code that you will need to get this to work. Also, we will be using the Async CTP to help make developing in Silverlight a little bit easier.

Okay, so let’s see what is required to create a Silverlight project. The web portion for hosting the service is complete and we can use it as it is with our Silverlight project.

In the Silverlight project, I added references to the Async CTP and the HttpContrib libraries.

Next I update my App.xaml.cs to look as follows:

public App()
{
	this.Startup += this.Application_Startup;
	this.Exit += this.Application_Exit;
	this.UnhandledException += this.Application_UnhandledException;

	InitializeComponent();

	HttpWebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
	HttpWebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
}

If you do not provide the last two lines of code, you will not be able to perform PUT or DELETE operations as Silverlight will default to use the browser’s network stack. You can read more about this in my blog post here.

Next, we create a link to the domain classes that was used for testing in my previous posts.

Finally, we will write the code to make a request to our generic service. I kept this example simple by simply providing code in the code-behind of the MainPage.xaml file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Domain;

namespace SilverlightTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            Get();
        }

        private void Get()
        {
            var repo = new SilverlightRepository("Customers");
            repo.Get<Customers>(
                (item) =>
                {
                    if (item == null)
                    {
						// do something.
                    }
                },
                (error) =>
                {
                    if (error == null)
                    {
						// display the error.
                    }
                }
            );
        }
    };
}

The main code to look at is the Get() method. In it we are using a new class, “SilverlightRepository”. This class wraps up our usage of the HttpContrib libraries as well as the Async CTP. It exposes a method Get<> that takes in two Action<> delegates. If we are able to successfully get data, then the first delegate is fired. If an error is encountered, then the second delegate is fired. This gives us the flexibility to either bind our data or display/log the error message.

Let’s look at the SilverlightRepository class now:

namespace SilverlightTest
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using HttpContrib;
    using HttpContrib.Client;
    using HttpContrib.Http;
    using System.Windows;
    using System.Text;

    public class SilverlightRepository
    {
        private string _uri;  // Example:  "http://localhost:18561/Customers";
        private string Uri
        {
            get { return _uri;}
            }

		#region ctor

        public SilverlightRepository(string service)
        {
            string hostName = Application.Current.Host.Source.Host;
            if (Application.Current.Host.Source.Port != 80)
            {
                hostName += ":" + Application.Current.Host.Source.Port;
            }
            _uri = "http://" + hostName + "/" + service;
        }

        #endregion

        public void Get<T>(Action<List<T>> completed,
            Action<string> onError) where T : class
        {
            string typeName = typeof(T).Name;
            string uri = Uri.ToString();

            SimpleHttpClient client = new SimpleHttpClient(uri);

            IHttpQueryProvider queryProvider = new HttpQueryProvider(client);

            var query = new HttpQuery<T>(queryProvider);

            string queryString = query.GetFullyQualifiedQuery(client).ToString();

            var task = query.ExecuteAsync();

            task.ContinueWith(t =>
            {
                Execute.OnUIThread(() =>
                {
                    if (!t.IsFaulted && t.IsCompleted && t.Result != null)
                    {
                        Debug.WriteLine("{0}: {1}", typeName, t.Result);
                        completed(t.Result.ToList());
                    }
                    else
                    {
                        string msg = GetExceptionMessage(t.Exception);
                        onError(msg);
                    }
                });
            });
        }
        public void Create<T>(T item, 
            Action<T> completed,
            Action<string> onError) where T : class
        {
            string typeName = typeof(T).Name;
            string uri = Uri;
            SimpleHttpClient client = new SimpleHttpClient(uri);

            var query = client.CreateQuery<T>();

            query.Create(item);

            string queryString = query.GetFullyQualifiedQuery(client).ToString();

            var task = query.ExecuteSingleAsync();

            task.ContinueWith(t =>
            {
                Execute.OnUIThread(() =>
                {
                    if (!t.IsFaulted && t.IsCompleted && t.Result != null)
                    {
                        Debug.WriteLine("{0}: {1}", typeName, t.Result);
                        completed(t.Result);
                    }
                    else
                    {
                        string msg = GetExceptionMessage(t.Exception);
                        onError(msg);
                    }
                });
            });
        }
        public void Update<T>(T item, 
            int id, 
            Action<T> completed,
            Action<string> onError) where T : class
        {
            string typeName = typeof(T).Name;
            string uri = Uri;
            SimpleHttpClient client = new SimpleHttpClient(uri);

            var query = client.CreateQuery<T>().Update(id, item);

            string queryString = query.GetFullyQualifiedQuery(client).ToString();

            var task = query.ExecuteSingleAsync();

            task.ContinueWith(t =>
            {
                Execute.OnUIThread(() =>
                {
                    if (!t.IsFaulted && t.IsCompleted && t.Result != null)
                    {
                        Debug.WriteLine("{0}: {1}", typeName, t.Result);

                        completed(item);
                    }
                    else
                    {
                        string msg = GetExceptionMessage(t.Exception);
                        onError(msg);
                    }
                });
            });
        }
        public void Delete<T>(T item, 
            int id, 
            Action<T> completed,
            Action<string> onError) where T : class
        {
            string typeName = typeof(T).Name;
            string uri = Uri;
            SimpleHttpClient client = new SimpleHttpClient(uri);

            var query = client.CreateQuery<T>().Delete(id);

            string queryString = query.GetFullyQualifiedQuery(client).ToString();

            var task = query.ExecuteSingleAsync();

            task.ContinueWith(t =>
            {
                Execute.OnUIThread(() =>
                {
                    if (!t.IsFaulted && t.IsCompleted)
                    {
                        Debug.WriteLine("{0}: {1}", typeName, t.Result);
                        completed(t.Result);
                    }
                    else
                    {
                        string msg = GetExceptionMessage(t.Exception);
                        onError(msg);
                    }
                });
            });
        }

    #region Helper

        private string GetExceptionMessage(Exception ex)
        {
            string result = null;
            if (ex.InnerException != null)
            {
                result = GetExceptionMessage(ex.InnerException);
            }
            else
            {
                result = ex.Message;
            }
            return result;
        }

    #endregion
    
    };
}

Okay, as you can see we are expecting the name of the service to be passed into the constructor. With the service name we then construct the Uri. Note that the way we are constructing the Uri is friendly for both developing and testing your application and running in production.

Next, we simply call the Get<> method passing in the corresponding type. We then use the helper SimpleHttpClient class exposed by the HttpContrib libraries. This class really makes it easy for use to consume the service that has been exposed. We then create an IHttpQueryProvider instance by passing in the client object to the constructor of the HttpQueryProvider class. We let the IHttpQueryProvider create our full query for our request and then we use the Async CTP to execute the request asynchronously.

We use the ContinueWith method to allow the thread to continue but call a delegate once a response has been returned. One we have a response we make sure that we marshal our data to the UI thread.

Finally, we inspect the response object to ensure that is has not faulted and is completed with data. If we pass this condition, then we execute the Action<> delegate with the results.

If we encountered an error then we execute the error Action<> delegate with the error message.

If you look at the remaining code for the other verbs, you can see that we are following the same pattern. You will notice that with the Get<> method, we used the IHttpQueryProvider to create our query but all other verb requests can come directly from the SimpleHttpClient directly calling the CreateQuery(…) method.

You have also noticed that I have a GetExceptionMessage(…) helper method. When an exception occurs on the server, it get wrapped up with a generic exception object and message. This really does no good to the client and so I am simply pulling the InnerException property to get the real message from the server.

Now that we have covered the service and creating the client, I am sure you are curious how we are getting our data. That is next on our agenda as I will be introducing a set of libraries via NuGet that will provide this functionality for you as well as give you data access.

Building a generic service using WCF Web API – Part III

December 20, 2011 1 comment

Before we write our client applications, I wanted to first introduce you to the power of the Test Client that is provided out of the box when you use the WCF Web API. This is a powerful tool that lets you test your services without ever needing to use Fiddler or any custom browser tool. It allows you to test all of the verbs that you are exposing.

In order for this to work you must ensure a single property, “EnableTestClient”, is set to true in our Global.asax.cs file:

protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.SetDefaultHttpConfiguration(new WebAPIConfiguration()
    {
        CreateInstance = (serviceType, context, request) => CreateInstance(serviceType), 
        EnableTestClient = true
    });

    RouteTable.Routes.MapServiceRouteForAssemblyOf<Customers>(ACCOUNT);
    RouteTable.Routes.MapServiceRouteForAssemblyOf<rv_o_Organization>(EGOV);
}

Now, that we have turned on our ability to use the Test Client, let’s take a look and see what it can give us. Based on the previous posts that we have covered, we are going to access one of the service routes and see what the Test Client show us:

It is very easy to access the Test Client for any of your services by simply appending “/test” to your URL. On the top-left side of the screen, we see two resources. At the bottom-left side of the screen, you see the history off all the requests you have made.

At the center-top of the screen, we see a placeholder for the HTTP verb and the URL of the request. Below this, there is the option to define/view the headers for the request. Below the Headers, we see the Body and can select the format of the request.

Finally, we have the Send button below the Body and then we see the Response section.

If you click on the first item in the Resources list, we get the following screen shot:

As you can see, the default Request is going to be GET. You can also see that the URL for the request is also provided by default.

If we click in the textbox for the HTTP verbs and see what our other options are:

Based on the URI, we only get the verbs that are supported with each request. GET and POST are the only two verbs that are supported with this request.

We are going to change the Headers from “*/*” to “application/json”. This will ensure that the response will come back in JSON.

Now we can click on the Send button and see what the result looks like for a simple GET:

We get to see quite a bit of information once we get a response. We see the Request time, Response time, and Duration. We see the Response code, Headers, and finally the Body of the response. This is pretty nice and it allow us to perform a lot of testing of our service before write a single client.

We seen what happens when we perform a GET, now let’s try and add a new record by performing a POST.

First, we change the verb to POST. We can leave the headers as they are. We then select the format of the body to JSON. We then write in our JSON to represent a new record. Finally we hit Send and wait for the response. With this response, we received a code of 201/Created. The response header and body then return to us the newly created record from the server.

What about an Update or Delete operation? Well, we now need to select the next item on the Resources list. We can check to see what verbs are supported for this request by clicking in the textbox. As you can see, we can perform either a PUT or DELETE.

We will leave the verb as a PUT. We need to provide the primary key to the record is in the path of the URL. Next we change the format of the body to JSON and paste in what we used to create the record but we also include the Id of the record as well as make some modifications. Finally we hit Send and wait for our reponse. We get a Reponse code of 200 and we are echoed back the record in the body of the response.

Deleting a record is even easier. All we need to do is change the verb to DELETE and ensure that the primary key to the record is in the path of the URL. Next we hit Send and await our response. We get a Response code of 200 and we are returned the total number of records affected by the delete.

The Test Client feature of the WCF Web API makes developing and testing services very fast with very little hassle. I simply hit F5 on my solution and then navigate my browser to the corresponding service I want to test.

NOTE: Make sure that your JSON is in the correct format or it may never hit your breakpoint.

That’s it for now. We will cover creating Silverlight and Console test clients in the next post.

Building a generic service using WCF Web API – Part II

December 19, 2011 1 comment

Okay, so we now have our service definition in place. Let’s take a look and see what it takes to get this service exposed in our web project. The first place that we start is the Global.asax.cs file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;
using Microsoft.ApplicationServer.Http;
using Domain;
using Domain2;
using Ninject;
using Microsoft.ApplicationServer.Http.Activation;

namespace Gofer.Web
{
    public class Global : System.Web.HttpApplication
    {
        public const string ACCOUNT = "Domain";
        public const string EGOV = "Domain2";

        protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.SetDefaultHttpConfiguration(new WebApiConfiguration() 
                {
                    CreateInstance = (serviceType, context, request) => CreateInstance(serviceType),
                    EnableTestClient = true 
                });

            RouteTable.Routes.MapServiceRouteForAssemblyOf<Customers>(ACCOUNT);
            RouteTable.Routes.MapServiceRouteForAssemblyOf<rv_o_Organization>(EGOV);
        }

        private object CreateInstance(Type serviceType)
        {
            object result = null;
            IKernel kernel = new StandardKernel();
            try
            {
                // The following is a sample entry for using the MapServiceRoute method:
                // RouteTable.Routes.MapServiceRoute<GoferService<Customers>>("Customer");
                // Hence the reason we need to pull the generic type from the GoferService.
                var genericType = serviceType.GetGenericArguments().FirstOrDefault();
                DataAccessRules rules = null;
                switch (genericType.Namespace)
                {
                    case ACCOUNT:
                        rules = GetAccountAtAGlanceRules(genericType);
                        break;
                    case EGOV:
                        rules = GetEgovRules(genericType);
                        break;
                }

                kernel.Bind(serviceType).ToSelf().WithConstructorArgument("rules", rules);

                result = kernel.Get(serviceType);
            }
            catch { }

            return result;
        }

        #region Rules

        private DataAccessRules GetAccountAtAGlanceRules(Type type)
        {
            var result = new DataAccessRules();
            result.AssemblyOf(type)
                .SetConnectionStringKey("aag_ConnectionString")
                .ShouldMap(x => x.Namespace == "Domain");
            return result;
        }
        private DataAccessRules GetEgovRules(Type type)
        {
            var result = new DataAccessRules();
            result.AssemblyOf(type)
                .SetConnectionStringKey("emgov_ConnectionString")
                .ShouldMap(x => x.Namespace == "Domain2");
            return result;
        }

        #endregion
    };
}

Just like any of the other examples you have seen with the WCF Web API, we are using the Routes property off of the RouteTable and calling the SetDefaultHttpConfiguration. We are doing something a little special in that we are using a lambda expression to call the CreateInstance(…) method as well as passing in the service type. On the next two lines of code, we see that we are calling the MapServiceRouteForAssemblyOf<T>(…) generic extension method. It is the combination of the CreateInstance() method and the MapServiceRouteForAssemblyOf<T>(…) generic extension method that makes everything work correctly.

Let’s look at the CreateInstance() method first. In this method we are setting up our dependency injection (DI) container. I am using Ninject for this example but you could use MEF or Unity or whatever you wanted as well. Next I am interrogating the Type object that was passed in. I know by convention that the only service that I am going to be dealing with is the generic service we created in the last blog post. Because of that, I know that the type is a generic type and I know that it only has one generic argument. Based on the generic type information, I examine what the namespace is for the domain object. I then perform a simple switch statement and get the correct DataAccessRules object for the corresponding namespace. This gives me the flexibility to support multiple domain objects that represent different data models and not need to recompile or do any additions with the exception of the MapServiceRouteForAssemblyOf<T>(…) call.

Finally, I call the Bind method on the IKernel object and tell it to pass in the newly created DataAccessRules object as a constructor parameter. I then ask the kernel to resolve the service type that was originally passed into the method and return that new object.

So far, we have seen how we are setting up our DI container and injecting a DataAccessRules object into the constructor. What we haven’t seen yet is how we are getting data access for all of our domain objects. Let’s take a look at the individual methods that get us our DataAccessRules object and then we will turn our attention to how we handle this for all of our domain objects.

Our DataAccessRules objects are created by either the GetAccountAtAGlanceRules(…) method or the GetEgovRules(…) method. The thing to take into consideration here is we are telling the rules object what connection string to use from the web.config file as well as specifying the namespace that we only want to load our objects from.

Now let’s shift gears and take a look at the MapServiceRouteForAssemblyOf<T>(…) generic extension method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ApplicationServer.Http;
using Microsoft.ApplicationServer.Http.Activation;
using Gofer.Web;

namespace System.Web.Routing
{
    public static class RouteCollectionExtension
    {
        public static void MapServiceRouteForAssemblyOf<T>(this RouteCollection routes,
            string domain,
            HttpConfiguration configuration = null,
            object constraints = null,
            bool useMethodPrefixForHttpMethod = true)
        {
            var type = typeof(T);
            var domainAssembly = System.Reflection.Assembly.GetAssembly(type);
            var types = domainAssembly.GetTypes().Where(x => x.Namespace == domain);

            foreach (var item in types)
            {
                string routePrefix = item.Name;
                Type gs = typeof(GoferService<>);
                Type constructed = gs.MakeGenericType(new Type[] { item });
                routes.MapServiceRoute(constructed, routePrefix, configuration, constraints,
                    useMethodPrefixForHttpMethod);
            }
        }
        public static void MapServiceRoute(this RouteCollection routes,
            Type serviceType,
            string routePrefix,
            HttpConfiguration configuration = null,
            object constraints = null,
            bool useMethodPrefixForHttpMethod = true)
        {
            if (configuration == null)
            {
                configuration = routes.GetDefaultHttpConfiguration();
            }

            if (routes == null)
            {
                throw new ArgumentNullException("routes");
            }

            var route = new WebApiRoute(routePrefix,
                new HttpServiceHostFactory() { Configuration = configuration }, serviceType);
            route.Constraints = new RouteValueDictionary(constraints);
            routes.Add(route);
        }
    };
}

Okay, so if we look at the first method, we see that we are accessing the assembly for which the type belongs. We then load only the objects that match the namespace that was passed into the method. Finally we loop through each type and construct the generic service that we created in our last post. With a single line entry that called the MapServiceRouteForAssemblyOf<T> we are able to map service routes for all of our objects. It is actually the second method that does the routing which is very easy to follow.

Let’s look at one last piece of the puzzle, the web.config:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <appSettings>
    <add key="aag_ConnectionString" value="Data Source=(local);Initial Catalog=AccountsAtAGlance;Integrated Security=SSPI;" />
    <add key="emgov_ConnectionString" value="Data Source=(local);Initial Catalog=emgov_data;Integrated Security=SSPI;" />
  </appSettings>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  </system.serviceModel>
</configuration>

As you can see, this is one of the reasons why I love the WCF Web API. There is nothing but the bare minimum required. I can now add as many connection strings as I want to the web.config and I only have to go to the Global.asax.cs file to make sure that it is wired in correctly.

In the next post, we will look at what the client side code looks like.

Categories: English Tags: , , ,