Monthly Archives: April 2008

Great MonoRail Development Blog

Ben Lovell has started a great series on incremental development with MonoRail.  This is exactly what a new (and not so new) Castle or MVC or TDD developer  needs to get going in the right direction.  He even is posting the code on Google.  Great work, Ben!

Advertisements

JSONP Support Added to ArcDeveloper REST

I have previously blogged about the ArcDeveloper REST Service that a few of us ESRI .NET developers have thrown together. Until today, the only format you could request was GeoJSON. Now, through the miracle of something-I-needed-on-a-project, I have added JSONP support to the project. For those of you who don’t know what JSONP is, it is JSON wrapped in a javascript call. So, if you have JSON that looks like:

{
“type”: “FeatureCollection”,
“features”: [
{
“type”: “Feature”,
“geometry”: null,
“properties”: {
“Facility”: “SI”,
“Shape_Area”: “4.93182604749608E-05”}
},
{
“type”: “Feature”,
“geometry”: null,
“properties”: {
“Facility”:”Test”,
“Shape_Area”: “2.27729778462692E-05”,
}
} ]
}

With JSONP, it looks like:

javascriptFunc(‘{
“type”: “FeatureCollection”,
“features”: [
{
“type”: “Feature”,
“geometry”: null,
“properties”: {
“Facility”: “SI”,
“Shape_Area”: “4.93182604749608E-05”}
},
{
“type”: “Feature”,
“geometry”: null,
“properties”: {
“Facility”:”Test”,
“Shape_Area”: “2.27729778462692E-05”,
}
} ]
}’);

In a nutshell, JSONP was created to get around the pesky same-origin policy that browsers use to keep AJAX calls from making requests to a domain outside of the hosted site. This can be a real bugaboo, especially when you have a distributed application where, for example, ArcGIS Server is on one box, your web server is on another, and Sharepoint is on another. With JSONP, the client call can be wrapped in a <script> tag, which does not have to adhere to the same-origin policy. The <script> tag comes back with your JSON wrapped in a javascript call you specify (more on this is a second) and voila! we are cooking with gas.

In order to successfully call a JSONP service, you have to specify the callback function as a querystring parameter. As such, you have to know which querystring parameter the service is expecting to hold the callback function name. So, if we define a local javascript function called ‘jsonpCallComplete(json)’, then the script block comes back as:

<script type=’text/javascript’ src=”http://otherdomainserver/restservice/query?format=jsonp&callbackFun=jsonCallComplete&#8217; > jsonpCallComplete(‘{“property”:”value” …etc…}’);</script>

Which fires your javascript call, passing in the JSON for you to do with as you please.

As a result of added this to the ArcDeveloper REST API, I had to make some “breaking” changes to the project. Firstly, the format must now be specified using the ‘f’ querystring parameter (i.e., f=json or f=jsonp) which maps to a ‘format’ parameter on the service methods. The value of the ‘f’ querystring parameter must match the name of the formatter, as configured in the Windsor configuration. Secondly, in order to pass the callback function name to the JSONP formatter, I chose to basically pass ALL the querystring paramters to every Formatter. That way, if another formatter needs a specific querystring parameter, it will supplied by the service manager for each request. Check the code for more details, if you are interested.

Dojo (a pretty danged good javascript framework) has native support for JSONP services, allowing you to, in essence, treat a cross-domain AJAX call as a same-origin AJAX call. The Dojo site has decent docs and a overview of Dojo is way beyond the scope of this post, but here is an example AJAX call to the ArcDeveloepr REST API on one box from a client site on another:

(you will need to do a dojo.require(‘dojo.io.script’) for this to work)

dojo.io.script.get({
url:”http://gisdev02/AGSRest/rest.svc/facility/Facilities&#8221;,
content: {
query:”name=’Airport'”,
f:’jsonp’ // specify the format
},
callbackParamName:’callback’, //specify the qs param to send the javascript func name
load:dojo.hitch(this,function(resp){
var featurecollection=dojo.fromJson(resp);
dojo.forEach(featurecollection.features,dojo.hitch(this,function(feat){
var opt = createNode(“option”);
opt.value=feat.properties.extent;
opt.innerHTML=feat.properties.Facility;// SEE? It’s JSON!
this.bookmarks.appendChild(opt);
}));
this.element.appendChild(this.bookmarks);})
}

Dojo is kind enough, in this case. to call the function defined in the ‘load’ property of the dojo.io.script.get method above. As far as your code knows, it’s just an AJAX call, but it only works for services that support JSONP.

So, that is JSONP support. I plan on checking in the code after some of the other ArcDeveloper types chime in on my “breaking” changes (mentioned above), which should be tomorrow.

By the way, for anyone developing there own JSONP services, here are a couple of things I ran into:

  • Make sure you strip all whitespace out of the JSON before streaming it back to the client. I used a Regex for this.
  • The trailing semi-colon ( ; ) on the JSONP call is, apparently, very important.

I’ll edit the post if I hit other issues in the testing.


Here’s What I Like!

I read a lot of blogs, and many of them have a page dedicated to utilities they use and books they like.  Those blogs are cool, and I want to be like them. So, here is my page of tools and books (and frameworks).  I plan to add to it as I remember stuff or find new toys.  Feel free to suggest any.


Castle Windsor and WCF: A Match Made in Heaven

(Note: I’ve been out for a bit due to new recent additions to my life. The first was a (third) daughter born 2 weeks early and the second is an aggressive vasectomy schedule. Too much information, you say? I agree.)

If you’ve read any of my other posts, you know I dig Castle Windsor. It’s cool and allows a “special” developer like me to look pretty smart without actually being all that smart. I also really like WCF, as I feel it lead the charge of “things Microsoft started getting right”, again helping me look smart by abstracting all the WS-*** and other service gobblety-gook out of my life. Since I REALLY like both of these technologies, I was hesitant to put them together, fearing I couldn’t take the shear joy it would create. However, Ayende and Craig have created the WCF Facility, allowing me to register my services on the Windsor container, and thus use dependency injection to handle all the stuff my services need. This post is a (hopefully) quick “how to” on this really cool facility.

(Note: This is my first foray into using Binsor for Windsor Configuration. All the smart guys were using it while I was still XMLing in the dark ages, so I had to follow suit.)

Step Uno: Write a Service

Let us create a simple WCF service. It looks like:

[ServiceContract()]

public interface IService1

{

[OperationContract]

string MyOperation1(string myValue);

[OperationContract]

void ThrowError();

}

public class Service1 : IService1

{

private ILogger logger; //Yes, yes, should init to a NullInstance.

public ILogger Logger

{

get { return logger; }

set { logger = value; }

}

#region IService1 Members

public string MyOperation1(string myValue)

{

logger.Info(“MyOperation1 called with {0}”,myValue);

return “Hello: “ + myValue;

}

public void ThrowError()

{

throw new Exception(“AAAAAAH!”);

}

#endregion

}

So, you see the service contract, you see the implementation. Please notice the following details:

  • I added an ILogger property. This is a dependency.
  • There is a method that just ralphs an error. Usually I am not as obvious with my errors, but at least I will be able to debug this one.

Usually, at this point, you’d open up the web.config file and start writing mountains of <service> tags and <behaviors> and all that. We aren’t going to do that. We are going to bring in Windsor to take care of all our needs. Yay!

Bring in da Noise, Bring in da Windsor

I am going to presume that you, the reader, knows about Windsor and, at least at a high level, how to configure it. Basically, for a web app (we are gonna host our services in IIS) you need to:

  • Write the configuration files for Windsor, consisting of properties, facilities, and components. Go read the castleproject.org site for some decent examples.
  • Register the container at startup.

As I stated previously, I am using Binsor to write my config files. (Tangent: I need to learn Boo. Ayende, is that book done yet?) Here goes:

import System;

import System.Reflection

import System.ServiceModel

import System.ServiceModel.Description from System.ServiceModel

import Castle.Facilities.Logging

import Castle.Facilities.WcfIntegration

import Ruprict.Grok.Castle.WcfIntegration.Core

facility LoggingFacility:

loggingApi = LoggerImplementation.Log4net

configFile = ‘log4net.config’

facility WcfFacility

component ‘windsor.service’, IService1, Service1:

ServiceModel = WcfServiceModel().Hosted() \

.AddEndpoints(WcfEndpoint.BoundTo(BasicHttpBinding()))

component ‘error.handler’,IServiceBehavior, LogExceptionHandler

component ‘metadata.behavior’,IServiceBehavior, ServiceMetadataBehavior:

HttpGetEnabled = true

This is Binsor 2.0 syntax, which is (from what I understand) yummier than ever. I do like it. It’s compact and readable and I don’t end up getting errors b/c I forgot to close a tag. Looking at the import statements, you see I bring in whatever namespaces I need, including my service namespace and any of it’s dependencies. Here, I’ve yanked in the ServiceModel stuff from WCF so I can hook up my IServiceBehavior extension classes, as well as some other Castle Facility namespaces (namely, the Logging facility). Then, I start defining things. I grab the LoggingFacility from Castle, telling it I am using Log4Net and pointing it at the right config file. Then it’s on to the star of our show, the WcfFacility. It seems odd that it just takes two words to bring in a facility that does so much. Ahh, simplicity, you are truly beautiful. Anyhoo, the first component is my WCF service (line 16) where you can see that I add a singular endpoint, bound to the BasicHttpBinding, um, binding. (NOTE: If you are using the BasicHttpBinding, like I am here, you don’t even have to specify a service model, as the facility will deduce it from the base address.) Finally, I add 2 more components, both IServiceBehaviors. For those that don’t know, IServiceBehavior is a way to extend WCF by create custom service (there are also endpoint and operation behaviors, all of which are treated the same by the WcfFacility) behaviors. In our example, I have created a LogExceptionHandler that will log errors to a log file. I also used a WCF core service behavior, ServiceMetatadataBehavior so I can use an HTTP GET to look at the service WSDL.

With the configuration defined, we have to get our IIS web app to use it, right? That’s done in the Global.asax by putting some code in the HttpApplication.Application_Start event.

public class Global : HttpApplication, IContainerAccessor

{

private static IWindsorContainer container;

protected void Application_Start(object sender, EventArgs e)

{

container = new WindsorContainer().Install(BinsorScript.FromFile(“windsor.boo”));

}

protected void Application_End(object sender, EventArgs e)

{

container.Dispose();

}

#region IContainerAccessor Members

public IWindsorContainer Container

{

get { return container;

}

#endregion

}

That single line in Application_Start tells Windsor that I am using Binsor and the name of my config file. Gorgeous!

Now, in order to host a WCF service in IIS, you need a .svc file as an endpoint, and (usually) web.config configuration sections out the yin-yang. We still need the former, pointing it to our WindsorServiceHostFactory and using the name from our Binsor config file.

<%@ServiceHost Language=”C#”

Service=”windsor.service” Factory=”Castle.Facilities.WcfIntegration.WindsorServiceHostFactory”

%>

Now, when we crank up the application, the Windsor Container will attach the IServiceBehaviors in the config to our services, automatically wiring up my LogExceptionHandler and ServiceMetadataBehavior. This is especially sexy when you have multiple services in a single application and they ALL get the behaviors. Furthermore, since my service has an ILogger property (remember that?) and I am also using the LogFacility, it will create my Log4Net logger and give my service an instance. POW! BLAM! KABLOOEY! This is how we do it.

I was going to put some examples of the service getting called using WcfTestClient.exe (free with .NET 3.5) so you could see my error behavior doing it’s thang as well as prove to you that we don’t need no stinking web.config sections, but I find them superfluous in a post that already is larger than I wanted it to be. If you have more questions, hit me with a comment.

So, in summary, the keypoints here are:

  • Windsor rocks, and the WcfFacility is all that and a bag of chips.
  • You can have web.config <service> section-less WCF services, complete with auto-wired behaviors and dependencies.
  • Ayende and Craig are really, really smart.

More Examples

These two posts (here and here) in the Castle Dev Google Group go through some more examples from Craig. You’ll even get to see me asking very basic questions. Also, Craig has promised he will post some stuff focusing on the client side of things, which should be very interesting.

Update: Another, example of the newer (2008/12/02) stuff here.

Reblog this post [with Zemanta]