Archive for November 2007

Toggle Resharper code analysis with C# 3.0

Since Resharper will not support C# 3.0 features until next year and I do not like working in Visual Studio without Resharper, I was happy when I ran across this post by Jeffrey Palermo: http://codebetter.com/blogs/jeffrey.palermo/archive/2007/11/28/temporarily-disable-code-analysis-for-single-code-file-with-resharper-3-0-2-and-vs-2008.aspx.  This is a good workaround for allow the annoying error highlights of correct C# 3.0 code.  Now if someone could combine this with a macro to toggle between Visual Studio and Resharper Intellisense, we would have the ideal workaround until 4.0 EAP.

Validations with WCF and Windsor

Yesterday, I posted a solution for intercepting WCF calls with IOperationInvoker for validation.  At the end of the article, I mentioned that you could probably get this integration working with Castle’s Validator if you did not want to use the Enterprise Library Validation Application Block.  I forgot that Windsor supports configuring components as WCF services.  While you could go the route that I suggested, you would probably be better served to take a look at Windsor’s WCF integration http://www.ayende.com/Blog/archive/2007/06/12/WCF-Windsor-Integration.aspx.  Then, you can use Castle Validator and configure your validations with attributes or Windsor.

Validations with WCF and JSON

Earlier I discussed getting WCF to work with JSON, and I wanted to talk a little more about validations.  I prefer attribute based validations for simple domain constaints and code validations for more complex validations.  The Validation Application Block (VAB) in the Enterprise LIbrary provides a great solution for validation.  While I think a lot of pieces of the Enterprise Library are a little too complex and poorly documented (i.e. ObjectBuilder), I really like the VAB.

 

VAB ships with integration for WCF.  It allows you to define attribute based validations on your service parameters like (I am borrowing this example from http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/04/06/11506.aspx):

 

[ServiceContract]
public interface IOrdersService
{
    [OperationContract]
    int CreateOrder(
        [NotNullValidator] string currency,
        [RangeValidator(1.0, RangeBoundaryType.Inclusive, 2.0, RangeBoundaryType.Inclusive)] double amount);
}
 

Now, when you call the CreateOrder method on the service, it will validate the parameters and make sure that currency and amount follow the specified validations.  Unfortunately, their are two limitations with the out of the box approach.  One, you cannot define validations using the Enterprise Library configuration (which I do not prefer but I can see how it is beneficial in some scenarios).  Second, the default WCF integration handles the validations by throwing a Fault that contains the validations details.  This does not play well with ExtJS because it expects a successful AJAX requests that contains a message specifying that there were validation errors.

 

I researched a couple of different ways to alter the out of the box integration.  Unfortunately, the out of box integration uses IParameterInspector which only allows you to inspect parameters as they are coming into the the service.  I come across a little discussed extension point of WCF called IOperationInvoker.  IOperationInvoker allows you to do before and after interception of WCF service calls.  The mean benefit of this is that it allows me to return validation error messages as a successful result or a service call through a defined contract like:

[ServiceContract]
public interface IOrdersService
{
    [FormValidation]
    [OperationContract]
    FormResult CreateOrder(
        [NotNullValidator] string currency,
        [RangeValidator(1.0, RangeBoundaryType.Inclusive, 2.0, RangeBoundaryType.Inclusive)] double amount);
}

 

Note the attribute [FormValidation] on the service.  This instructs the WCF service host to use the IOperationInvoker that I defined for the service.  I also llike this approach because I do not have to define the validation behavior in XML, and can instead decorate my service.  My FormResult object contains three properties: Successful(), Errors (which returns ValidationDetails[]), and Result (which returns the actual result). 

 

Although I did not implement my IOperationInvoker this way, I believe that you can also return the ValidationResults as an out parameter if you prefer that method signature style but I am not sure how/if this works with WCF REST services.  Also, this approach can be integrated with validations configured in XML. 

 

Ff you do not want to be tied to the Enterprise Library, you should be able to apply this approach to other frameworks.  Castle has a validation component that has similar functionality to the VAB.

 

Here is a link to the source.

links for 2007-11-20

Google Reader Needs a Mute Button

Whenever something a bunch of tech bloggers get excited about something, I always wish there was a mute conversation feature in Google Reader.  I am not quite sure how it would work — maybe off of post title similarity or when a content match algorithm says one article is too similar to another.  Maybe it could give you the option of how conservative or aggressive the matching is.

 

I really only wanted to know one time that Visual Studio 2008 was released today and not have to deal with the inevitable flood of posts on the topic for the remainder of the week.

links for 2007-11-09

Building a Generic DAO / Repository with LINQ

 

I have been working on a generic DAO / Repository pattern for LINQ on and off the past couple of days.  Being a long time Hibernate user, I was little skeptical that LINQ would provide the flexibility that I always got with Hibernate — but so far I have not been disappointed.  I will see what happens in the future when I have to get LINQ to map to a poor designed legacy database =).

 

In 3-tier design, a repository pattern is necessary because it helps make our service layer easier to test.  It is always good to have all of your code that generates your SQL in one place.  Imagine making your DataContext available to all tiers of your applications.  Have fun tracing through ASPX pages, web services, business layer classes trying to find who used a crazy lambda expression that is causing your database to crash.

 

Unfortunately, LINQ to SQL’s main class for dealing with data is DataContext — which is a concrete class with non-virtual methods.  That means that the generated class is pretty much impossible to unit test.  There have been some discussions on how to make LINQ more testable, but they involve editing the generated code.  I really do not understand the design decision in not having an interface IDataContext.

 

Anways, let’s move on to some code.  Any generic repository should offer the ability to do a couple of things CRUD methods, find methods, and paging/sorting.  Let’s start with the interface IRepository (for brevity, I am removing all of my comments):

 

   1: public interface IRepository<E, K> : IDisposable where E : class
   2: {
   3:  
   4:     Expression<Func<E, bool>> GetKeyLambda(K id);
   5:  
   6:     K Save(E group);
   7:  
   8:     void Update(K id);
   9:  
  10:     void Delete(K groupId);
  11:  
  12:     E Find(K id);
  13:  
  14:     IEnumerable<E> FindAll();
  15:  
  16:     PagedResult<E> FindAll(int start, int limit);
  17:  
  18:     PagedResult<E> FindAll(int start, int limit, string property, string sortDirection);
  19:  
  20:     PagedResult<E> FindAll(int start, int limit, string property, Expression<Func<E, bool>> sortLambda);
  21:  
  22: }
  23:  

 

PagedResult is a simple class that contains the query results and and the total count:

 

   1: public class PagedResult<T>
   2: {
   3:  
   4:     public PagedResult(IEnumerable<T> results, int totalCount)
   5:     {
   6:         Results = results;
   7:         TotalCount = totalCount;
   8:     }
   9:  
  10:     public IEnumerable<T> Results { get; set; }
  11:  
  12:     public int TotalCount { get; set; }
  13:  
  14: }

 

Now we have a simple interface that defines a number of our data access methods and can be unit tested.  Now let’s create our base repository class.  We want to be able to pass in the DataContext we are using to the generic repository:

 

   1: public class Repository<E, K> : IRepository<E, K> where E : class
   2: {
   3:     protected DataContext _dataContext;
   4:  
   5:     public Repository()
   6:     {
   7:     }
   8:  
   9:     public Repository(DataContext dataContext)
  10:     {
  11:         _dataContext = dataContext;
  12:     }
  13:  
  14:     ...
  15:     
  16: }

 

If you want to look to create your DataContext using a connection string, you can you subclass Repository:

 

   1: public abstract class AdventureWorksRepositoryBase<E, K> : Repository<E, K> where E : class
   2: {
   3:  
   4:     private const string ADVENTUREWORKS_CONNECTION_STRING_KEY = "Adventureworks.SQL";
   5:  
   6:     public AdventureWorksRepositoryBase()
   7:     {
   8:         if (_dataContext == null)
   9:         {
  10:             ConnectionStringSettingsCollection connectionStrings = ConfigurationManager.ConnectionStrings;
  11:             if (connectionStrings == null || connectionStrings.Count == 0)
  12:             {
  13:                 throw new Exception("Could not find connection string configuration section");
  14:             }
  15:  
  16:             ConnectionStringSettings connectionStringSection = connectionStrings[INTEGRAL_CONNECTION_STRING_KEY];
  17:             if (connectionStringSection == null)
  18:             {
  19:                 throw new Exception(String.Format("Could not find the connection string for the AdventureWorks Database. " +
  20:                   "Please check the App.Config or Web.Config for the Connection string key: {0}", ADVENTUREWORKS_CONNECTION_STRING_KEY ));
  21:             }
  22:             _dataContext = new AdventureWorksDataContext(connectionStringSection.ConnectionString);
  23:         }
  24: 
  25:     }

 

Since we only doing the DataContext lookup on construction, remember that this object should not be treated as a singleton.  Now back to our base Repository class.  Let’s implemented the simplest method — FindAll():

 

   1: public virtual IEnumerable<E> FindAll()
   2: {
   3:     return _dataContext.GetTable<E>();
   4: }

 

LINQ allows you to retrieve any object by using the generic GetTable method.  Most LINQ examples you see show you something like: db.Customers which can also be written as: db.GetTable<Customers>.  This is useful since we are writing a generic repository.

 

For the Find, Delete, and Update, and Save methods, we need to have a way to find our object through a Lambda expression.  Using straight LINQ to SQL, we would just write our find method by doing:

 

   1: from c in _dataContext.Customers
   2: where c.Id == 1
   3: select c; 

 

That does not work with the generic Repository because we have no idea what c is at compile time.  So we will provide two methods to generate a lambda expression that lets us select by our primary key:

 

   1: public virtual String GetKeyProperty()
   2: {
   3:     return "Id";
   4: }
   5:  
   6: public virtual Expression<Func<E, bool>> GetKeyLambda(K id)
   7: {
   8:     var parameter = Expression.Parameter(typeof(E), "e");
   9:     var propId = Expression.Property(parameter, typeof(E).GetProperty(GetKeyProperty()));
  10:     return Expression.Lambda<Func<E, bool>>(Expression.Equal(propId, Expression.Constant(id)), parameter);
  11: }

 

Expression trees are a little outside the scope of what I am covering, but the GetKeyLambda method is equivalent to c => c.Id == id.  We are assuming that our tables using Id as the common name for their primary key column, but the methods our virtual so they can be changed.  If you have a lot of different primary key names, you might want to implement an attribute to add to your repository subclass.  Also, GetKeyLambda can be overrode so that you can create a lambda expression to select a composite key: c => c.Key1 == id1 && c.Key2 == id2.

 

Now that we have a generic way of select our primary key, we can implement some of our other methods:

 

   1: public virtual E Update(K id)
   2: {
   3:     Find(id));
   4: }
   5:  
   6: public void Delete(K id)
   7: {
   8:     var removeQuery = _dataContext.GetTable<E>().Single(GetKeyLambda(id));
   9:     _dataContext.GetTable<E>().Remove(removeQuery);
  10: }
  11:  
  12: public virtual E Find(K id)
  13: {
  14:     return _dataContext.GetTable<E>().Single(GetKeyLambda(id));
  15: }

 

The update method does not really do anything besides a find, because to update we just edit the properties directly on our object.  I put it in there so that subclasses could modify the behavior.  The save method is a little tougher because we want to return the primary key:

 

   1: protected static Dictionary<Type, MetaDataMember> KEY_CACHE = new Dictionary<Type, MetaDataMember>();
   2:  
   3: public virtual K Save(E entity)
   4: {
   5:     DataContext db = _dataContext;
   6:     MetaDataMember key = null;
   7:     if (!KEY_CACHE.ContainsKey(typeof(E)))
   8:     {
   9:         ReadOnlyCollection<MetaDataMember> md =
  10:             db.Mapping.MappingSource.GetModel(db.GetType()).GetMetaType(typeof (E)).DataMembers;
  11:         int keyCount = 0;
  12:         foreach (MetaDataMember mdm in md)
  13:         {
  14:             if (mdm.IsPrimaryKey)
  15:             {
  16:                 key = mdm;
  17:                 keyCount++;
  18:             }
  19:         }
  20:  
  21:         if (keyCount == 0)
  22:         {
  23:             throw new Exception(
  24:                 String.Format(
  25:                     "Could not find a primary key for entity {0}.  You must override the Save method to persist this entity.",
  26:                     entity));
  27:         }
  28:  
  29:         if (keyCount > 1)
  30:         {
  31:             throw new Exception(
  32:                 String.Format("The base Repository does not support composite keys (Your entity {0} has more than one primary key).  You must override the save method in your subclass.",
  33:                 entity));
  34:         }
  35:         KEY_CACHE[typeof(E)] = key;
  36:     }
  37:     else
  38:     {
  39:         key = KEY_CACHE[typeof(E)];
  40:     }
  41:     _dataContext.GetTable<E>().Add(entity);
  42:     _dataContext.SubmitChanges();
  43:  
  44:     return (K)entity.GetType().InvokeMember(key.Member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, entity, null);
  45: }

 

Here we use the metadata provided by LINQ to SQL to find the primary key in our classes.  For simplicity, this example only handles one primary key per table, but again you can subclass if you want to use a composite key.  I am caching the key lookup in this method, but I would not be suprised to find out it runs faster uncached.  I still need to test this out.

 

Implementing a repository per table now becomes simple:

 

   1: public interface ICustomerRepository : IRepository<Customer, int>
   2: {
   3:  
   4:   Customer SelectCustomerBySomeComplicatedQuery(...);
   5:  
   6: }
   7:  
   8: public class CustomerRepository : AdventureWorksRepositoryBase<Customer, int>, ICustomerRepository
   9: {
  10:     
  11:     public void SelectCustomerBySomeComplicatedQuery(...)
  12:     {
  13:         ...
  14:     }
  15:  
  16: }

 

So, how to we use our repository?

 

   1: using (CustomerRepository repository = new CustomerRepository())
   2: {
   3:   repository.Delete(1);
   4:   Customer customer = repository.Find(1);
   5:   customer.FirstName = "Ted"; //This will change the value in the database
   6: }

 

Note that we have not told that database to submit our changes yet anywhere.  That is why our Repository interface extends IDisposable and we are using the using keyword.  On our Repository, Dispose() handles synchronizing the state of our entities with the database:

 

   1: public void Dispose()
   2:  {
   3:      _dataContext.SubmitChanges();
   4:  }

 

This post is getting long, so I will leave out the paging methods for now.  I would love to see someone take this simple design and make it a lot better as I am certain that it can be greatly enhanced.  I am really only supporting the simplest use cases for data access. 

More WCF, JSON, and ExtJS

As I have been working with WCF 3.5 and JSON more, I have started to understand the model a little better.  The important thing to understand is the effect using WebMessageBodyStyle.Wrapped and WebMessageBodyStyle.Bare will have on the JSON serialization. 

If you have a operation like this:

   1: [OperationContract]
   2: [WebInvoke(
   3:     BodyStyle = WebMessageBodyStyle.Bare,
   4:     RequestFormat = WebMessageFormat.Json,
   5:     ResponseFormat = WebMessageFormat.Json,
   6:     UriTemplate = "/Find")]
   7: Person Find(int id);

You can use WebMessageBodyStyle.Bare.  That is because you are passing a simple parameter to the service that does not require any serialization and you are returning void.  This seems to be the only situation in which WebMessageBodyStyle.Bare is useful.  If you have a contract that takes a DataContract or multiple input parameters, you have to use WebMessageBodyStyle.Wrapped.

So what does Wrapped mean?  Without the documentation, I am guessing that it means it will wrap the result with a root object.  The root object always seem to be the name of the method invoked with the string ‘Result’ on the end.  So, my Person would look like:

   1: { "PersonResult" : { "Id" : 1", "FirstName" : "John", "LastName" : "Smith } }

This is not necessarily ideal for ExtJS because it is not expecting the results to not have root object.  So, here is a WCFJsonReader that will allow you to use ExtJS and WCF more easily:

   1: /**
   2:  * @class Ext.data.WCFJsonReader
   3:  * @extends Ext.data.JsonReader
   4:  *
   5:  * Custom reader for reading data from WCF.  If you are using WebMessageBodyStyle.Wrapped, then WCF adds a root object to your
   6:  * JSON result:
   7:  * 
   8:  * { "MethodResult": { "Count" : 0, "Objects": [ ... ] } }
   9:  *
  10:  * Ext does not expect the result to have a root object before parsing, so this class will remove it.  
  11:  */
  12: Ext.data.WCFJsonReader = Ext.extend(Ext.data.JsonReader, {
  13:     /* @cfg {Boolean} Sets whether or not the OperationContract has the is using WebMessageBodyStyle.Wrapped */
  14:     wrapped: true,
  15:     /**
  16:      * If wrapped is set to true, we will strip WCF's wrap object
  17:      */
  18:     read : function(response){
  19:         var json = response.responseText;
  20:         var o = eval("("+json+")");
  21:         if(!o) {
  22:             throw {message: "JsonReader.read: Json object not found"};
  23:         }
  24:         if (this.wrapped) {
  25:             for (var prop in o) {
  26:                 if (typeof prop === 'string' && prop.substr(prop.length-6,prop.length) == 'Result') {
  27:                     o = this.convert(o[prop]);
  28:                     break;
  29:                 }
  30:             }
  31:         }
  32:         if(o.metaData){
  33:             delete this.ef;
  34:             this.meta = o.metaData;
  35:             this.recordType = Ext.data.Record.create(o.metaData.fields);
  36:             this.onMetaChange(this.meta, this.recordType, o);
  37:         }
  38:         return Ext.data.WCFJsonReader.superclass.readRecords.call(this, o);
  39:     },
  40:     //private 
  41:     convert : function(o) {
  42:         var newResult = new Object();
  43:         for (var rootProp in o) {
  44:             newResult[rootProp] = o[rootProp];
  45:         }
  46:         return newResult;
  47:     }
  48: });

Now you can use the WCFJsonReader instead of the JsonReader with your grids and forms, and everything should work fine.  Basically, the class removes the wrap object from the result so that ExtJS can process it the way it expects it.

I also got ExtJS forms working with the Validation Application Block’s WCF integration today — sort of.  I ended up rolling my own solution since VAB default WCF integration just throws a FaultException when a validation error errors.  The goal is to have the client return the error messages — not throw an error that contains the messages.  It probably was not designed with POX scenarios in mind.  I will try to find some time to post the solution later.

links for 2007-11-06

WCF 3.5 JSON and ExtJS

I have been working for the past couple of days working with WCF’s JSON support and ExtJS. I had some trouble finding good examples beyond sending and retrieving simple data types. After spending some time searching and one forum post, I finally got a complete prototype up and going.

 

I am going to create a simple PersonService to show the functionality. I will start out by creating two DataContract’s that we will use with our PersonService.

 


   1:      [DataContract]
   2:      public class Person
   3:      {
   4:          private Guid _id = Guid.NewGuid();
   5:          private string _firstName;
   6:          private string _lastName;
   7:          private DateTime _dateOfBirth;
   8:          private Address _address;
   9:          private List<Person> _children;
  10:   
  11:          [DataMember]
  12:          public Guid Id
  13:          {
  14:              get { return _id; }
  15:              set { _id = value; }
  16:          }
  17:   
  18:          [DataMember]
  19:          public string FirstName
  20:          {
  21:              get { return _firstName; }
  22:              set { _firstName = value; }
  23:          }
  24:   
  25:          [DataMember]
  26:          public string LastName
  27:          {
  28:              get { return _lastName; }
  29:              set { _lastName = value; }
  30:          }
  31:   
  32:          [DataMember]
  33:          public DateTime DateOfBirth
  34:          {
  35:              get { return _dateOfBirth; }
  36:              set { _dateOfBirth = value; }
  37:          }
  38:   
  39:          [DataMember]
  40:          public Address Address
  41:          {
  42:              get { return _address; }
  43:              set { _address = value; }
  44:          }
  45:   
  46:          [DataMember]
  47:          public List<Person> Children
  48:          {
  49:              get { return _children; }
  50:              set { _children = value; }
  51:          }
  52:   
  53:      }
  54:   
  55:      [DataContract]
  56:      public class Address
  57:      {
  58:          
  59:          private string _address1;
  60:          private string _address2;
  61:          private string _city;
  62:          private string _state;
  63:          private string _zipCode;
  64:   
  65:          [DataMember]
  66:          public string Address1
  67:          {
  68:              get { return _address1; }
  69:              set { _address1 = value; }
  70:          }
  71:   
  72:          [DataMember]
  73:          public string Address2
  74:          {
  75:              get { return _address2; }
  76:              set { _address2 = value; }
  77:          }
  78:   
  79:          [DataMember]
  80:          public string City
  81:          {
  82:              get { return _city; }
  83:              set { _city = value; }
  84:          }
  85:   
  86:          [DataMember]
  87:          public string State
  88:          {
  89:              get { return _state; }
  90:              set { _state = value; }
  91:          }
  92:   
  93:          [DataMember]
  94:          public string ZipCode
  95:          {
  96:              get { return _zipCode; }
  97:              set { _zipCode = value; }
  98:          }
  99:   
 100:      }

 

I have three complex types on my Person entity: a DateTime, an Address, and a List<Person>. I have done this so that I can show how these work. Now, I define the ServiceContract for my Person service.

 

   1:      [ServiceContract]
   2:      public interface IPersonService
   3:      {
   4:   
   5:          [OperationContract]
   6:          [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped,
   7:              RequestFormat = WebMessageFormat.Json,
   8:              ResponseFormat =  WebMessageFormat.Json,
   9:              UriTemplate = "/Create")]
  10:          Guid Create(Person person);
  11:   
  12:          [OperationContract]
  13:          [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare,
  14:              RequestFormat = WebMessageFormat.Json,
  15:              ResponseFormat = WebMessageFormat.Json,
  16:              UriTemplate = "/Get")]
  17:          Person Get(int id);
  18:   
  19:          [OperationContract]
  20:          [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped,
  21:              RequestFormat = WebMessageFormat.Json,
  22:              ResponseFormat = WebMessageFormat.Json,
  23:              UriTemplate = "/GetAll")]
  24:          List<Person> GetAll();
  25:   
  26:      }

 

You will have to add a reference to System.ServiceModel.Web in your project for this to compile. A couple things to note about what I implemented. You can WebMessageFormat.Xml to send use XML as the payload for your request and response. The WebGet (as opposed to WebInvoke) attribute allows clients to use your services using HTTP GET. However, if you do not have the requirement for cross domain clients accessing your wbe services, then you should use the WebInvoke attribute. Also, WebGet does not support binding parameters to complex types.

 

Here’s a simple implementation of our ServiceContract that returns some sample data. For brevity, I am doing some checking to make sure the serialization occurs but of course you would actually use some integration tests.

 

   1:      public class PersonService : IPersonService
   2:      {
   3:   
   4:          public Guid Create(Person person)
   5:          {
   6:              NotNull(person.FirstName, "FirstName");
   7:              NotNull(person.LastName, "LastName");
   8:              NotEmpty(person.Children);
   9:              return Guid.NewGuid();
  10:          }
  11:   
  12:          public Person Get(int id)
  13:          {
  14:              if (id != 1) throw new ArgumentException("Expected 1 for ID");
  15:              return new Person()
  16:              {
  17:                  FirstName = "John",
  18:                  LastName = "Smith",
  19:                  DateOfBirth = DateTime.Now,
  20:                  Address = new Address()
  21:                  {
  22:                      Address1 = "123 Capitol St.",
  23:                      Address2 = "Suite 10",
  24:                      City = "Indianapolis",
  25:                      State = "IN",
  26:                      ZipCode = "46204"
  27:                  },
  28:                  Children = GetAll()
  29:              };
  30:          }
  31:   
  32:          public List<Person> GetAll()
  33:          {
  34:              return new List<Person>
  35:                  {
  36:                      new Person() { FirstName = "Steve", LastName = "Smith", DateOfBirth = DateTime.Now },
  37:                      new Person() { FirstName = "Sally", LastName = "", DateOfBirth = DateTime.Now }
  38:                  };
  39:          }
  40:   
  41:          private static void NotNull<T>(T o, string paramName) where T : class
  42:          {
  43:              if (o == null) throw new ArgumentNullException(paramName);
  44:          }
  45:   
  46:          private static void NotEmpty<T>(ICollection<T> collection)
  47:          {
  48:              if (collection == null || collection.Count == 0) throw new ArgumentException("Collection was empty");
  49:          }
  50:   
  51:      }

 

And the configuration for our service.

 

   1:      <system.serviceModel>
   2:          <behaviors>
   3:        <endpointBehaviors>
   4:          <behavior name="jsonBehavior">
   5:            <webHttp />
   6:          </behavior>
   7:        </endpointBehaviors>
   8:              <serviceBehaviors>
   9:                  <behavior name="WebService1.PersonServiceBehavior">
  10:                      <serviceMetadata httpGetEnabled="true"/>
  11:                      <serviceDebug includeExceptionDetailInFaults="true"/>
  12:                  </behavior>
  13:              </serviceBehaviors>
  14:          </behaviors>
  15:          <services>
  16:              <service behaviorConfiguration="WebService1.PersonServiceBehavior" name="WebService1.PersonService">
  17:                  <endpoint behaviorConfiguration="jsonBehavior" address="" binding="webHttpBinding" contract="WebService1.IPersonService"/>
  18:                  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  19:              </service>
  20:          </services>
  21:      </system.serviceModel>

 

Now for the fun part, actually working with our services. Whatever AJAX library you are using, you have to make sure that your POSTs are sending the header: ‘application/json’.  Unless you change this behavior explicilty, ExtJS by default sends a default header like x-form-urlencoded with your posts.  So when I added application/json as a heaeder, it would send ‘x-form-urlencoded,application/json’ as the header.  This does not work — WCF will simply ignore your requests.  I corrected this by setting ExtJS to only send ‘application/json’ (see code below).

 

   1:      <script type="text/javascript" src="ext-base.js"></script>    
   2:      <script type="text/javascript" src="ext-all-debug.js"></script>    
   3:      <script type="text/javascript" language="javascript">
   4:          Ext.onReady(function() {
   5:              Ext.lib.Ajax.defaultPostHeader = 'application/json';
   6:   
   7:              var child = {
   8:                              person: {
   9:                                  FirstName: 'Tom',
  10:                                  LastName: 'Doe',
  11:                                  DateOfBirth: new Date(),
  12:                              }
  13:              }
  14:   
  15:              var request = {
  16:                  person: {
  17:                              FirstName: 'Jane',
  18:                              LastName: 'Doe',
  19:                              DateOfBirth: '\/Date(62831853071)\/',
  20:                              Address: {
  21:                                  Address1: '101 Capital St.',
  22:                                  Address2: 'Suite 100',
  23:                                  City: 'Indpls',
  24:                                  State: 'IN',
  25:                                  ZipCode: '46220'
  26:                              },
  27:                              Children: [ child, child ]
  28:                           }                
  29:              };
  30:              
  31:              var onFailure = function(r, opts) {
  32:                  Ext.get("errors").insertHtml('afterend', '<br/><br/>' + r.responseText, false);
  33:              }
  34:              
  35:              Ext.Ajax.request({
  36:                  url: '/PersonService.svc/Create',
  37:                  method: 'POST',
  38:                  params: Ext.util.JSON.encode(request),
  39:                  success: function(response, options) {
  40:                      Ext.get('create-p').update(response.responseText);
  41:                  },
  42:                  failure: onFailure
  43:              });
  44:              Ext.Ajax.request({
  45:                  url: '/PersonService.svc/Get',
  46:                  method: 'POST',
  47:                  params: 1,
  48:                  success: function(response, options) {
  49:                      Ext.get('get-p').update(response.responseText);
  50:                  },
  51:                  failure: onFailure
  52:              });
  53:              Ext.Ajax.request({
  54:                  url: 'PersonService.svc/GetAll',
  55:                  method: 'POST',
  56:                  success: function(response, options) {
  57:                      Ext.get('getall-p').update(response.responseText);
  58:                  },
  59:                  failure: onFailure            
  60:              });
  61:          });
  62:      </script>
  63:      <h3>Create:</h3>
  64:      <p id="create-p"></p>
  65:      <h3>Get:</h3>
  66:      <p id="get-p"></p>    
  67:      <h3>GetAll:</h3>
  68:      <p id="getall-p">
  69:      </p>
  70:      <p id="errors">
  71:      </p>

 

I’ll leave it up to you to see the output, but you should see the JSON representation of the objects returned by the service.

 

A couple of other items to note.  If you are using Ext forms, just name your form fields with the same values as the properties on your objects.  Then if you want to serialize a form as a parameter, just use: { ‘person’ : form.getValues(false) }.  I am reusing the same form often for insert and update, so sometimes I have to remove a parameter.  When I want to do that, I use the Javascript ‘delete’ keyword to remove the property. Also, I highly recommend using Firefox along with Firebug and Tamper Data to debug the communication between your services and the page. Tamper Data lets you change the values of your POST parameters (like IE Fiddler). The WCF Service Trace Viewer is also very helpful.

 

I need to investigate wiring the WCF services to the Enterprise Library’s Validation Application Block.  It ships with WCF integration, but I have not tested using it with JSON and ExtJS forms.

 

Keep in mind that you can always use ASP.NET AJAX and ScriptManager to generate Javascript proxies for you. The reason I choose to go this route was simply because I did not want to introduce a dependency on ASP.NET for my application because I am using ExtJS. For most scenarios where you are already using ASP.NET AJAX, it is probably the best solution for getting started.

 

References: