In case you missed it, there is a Hackathon that is going on right now (the submission deadline is tomorrow so you still have time to throw a quick mobile project together).
As part of the Hackathon event in St. Louis last week I gave a brief presentation on how to quickly and easily add a RESTful JSON webservice to your modules, or even create a simple module to do this yourself. I have the source code for this presentation on Codeplex under the dnnweb project, http://dnnweb.codeplex.com/
The idea behind this is that in order to create a mobile app that does something with DNN you likely need to expose some data, and why not do it in a very quick and easy way, with RESTFul implementations and JSON data that works very well with javascript. For an example project you should check out the DNN Pulse application that Joe blogged about earlier.
The code is in C#, but is really simple, you should be able to get it into a VB project fairly easily. In this post I’m going to talk about the code and what is going on.
One word of warning, this project that you can download an install is not using any type of authentication right now, you can add it to a site, and it someone calls svc/users they will get a list of all your users, it is just provided for sample purposes right now.
The first thing is a quick modification to your web.config file, if you’re using IIS7 you can easily setup an HTTPHandler that will allow your web service to respond to incoming requests, such as
http://PORTALALIAS/svc/users
http://PORTALALIAS/svc/roles
http://PORTALALIAS/svc/user/USERNAME
With DNN5 this becomes very easy to do in your module’s manifest file. With the project linked above I have already made this change for you, here’s the sample code for that configuration
1: <component type="Config">
2: <config>
3: <configFile>web.config</configFile>
4: <install>
5: <configuration>
6: <nodes>
7: <node path="/configuration/system.web/httpHandlers" action="update" key="path" collision="overwrite">
8: <add verb="GET" path="svc/*" type="com.christoc.dnn.dnnwebservices.Services.GetHandler, dnnwebservices" />
9: </node>
10: <node path="/configuration/system.webServer/handlers" action="update" key="name" collision="overwrite">
11: <add name="DnnWebServicesGetHandler" verb="GET" path="svc/*" type="com.christoc.dnn.dnnwebservices.Services.GetHandler, dnnwebservices" preCondition="integratedMode" />
12: </node>
13: </nodes>
14: </configuration>
15: </install>
16: <uninstall>
17: <configuration>
18: <nodes />
19: </configuration>
20: </uninstall>
21: </config>
22: </component>
The next thing you need to do is to setup the HTTPHandler itself, in the example code I setup the Get Handler which exists in Services/GetHandler.cs, you basically need to implement IHttpHandler on the class
1: public class GetHandler : IHttpHandler
2: {
3: #region IHttpHandler Members
4:
5: public bool IsReusable
6: {
7: get { return false; }
8: }
9:
10: public void ProcessRequest(HttpContext context)
11: {
In order to do the JSON side of things, which stands for JavaScript Object Notation, I pulled in an opensource library from codeplex, http://json.codeplex.com/
In the processing for the handler I setup some method calls, one for getting all users, get a specific user, and one for get all roles for a portal. These are pretty simple, here they are in the ProcessRequest implementation
1:
2: public void ProcessRequest(HttpContext context)
3: {
4: HttpResponse response = context.Response;
5: var written = false;
6:
7: //because we're coming into a URL that isn't being handled by DNN we need to figure out the PortalId
8: SetPortalId(context.Request);
9:
10: //get all roles for a portal
11: if(context.Request.Url.AbsolutePath.IndexOf("roles")>0 && written == false)
12: {
13: response.Write(GetRolesJson(PortalId));
14: written = true;
15: }
16:
17: //get back a listing of
18: if (context.Request.Url.AbsolutePath.IndexOf("users") > 0 && written == false)
19: {
20: response.Write(GetUsersJson(PortalId));
21: written = true;
22: }
23:
24: //get back a single user
25: if (context.Request.Url.AbsolutePath.IndexOf("user") > 0 && written == false)
26: {
27: //get the username to lookup
28: response.Write(GetUserJson(PortalId, context.Request));
29: written = true;
30: }
31:
32: }
And the implementation of one of those calls, which goes through the DNN API
1: ///<summary>
2: /// Return all users for a portal in formatted json string
3: /// </summary>
4: /// <param name="portalId">portalid</param>
5: private static string GetUsersJson(int portalId)
6: {
7: //get a list of all roles and return it in json
8: var uc = new UserController();
9: var users = UserController.GetUsers(portalId);
10: var usersOutput = string.Empty;
11: foreach (var t in users)
12: {
13: var output = JsonConvert.SerializeObject(t, Formatting.Indented);
14: usersOutput += output;
15:
16: }
17: return usersOutput;
18: }
And one last thing, in order to make the various calls, you also need to know how to get your PortalId based on the incoming URL.
1: ///<summary>
2: /// Set the portalid, taking the current request and locating which portal is being called based on this request.
3: /// </summary>
4: /// <param name="request">request</param>
5: private void SetPortalId(HttpRequest request)
6: {
7:
8: string domainName = DotNetNuke.Common.Globals.GetDomainName(request, true);
9:
10: string portalAlias = domainName.Substring(0,domainName.IndexOf("/svc"));
11: PortalAliasInfo pai = PortalSettings.GetPortalAliasInfo(portalAlias);
12: if (pai != null)
13: PortalId = pai.PortalID;
14: }
15:
16: public static int PortalId { get; set; }
The rest of the module project right now doesn’t do anything, eventually I will add authentication and some display functionality to the services and the module, but for now it’s just something quickly put out there. Download it, tear it apart, and start working on your own web services.
A reminder about the Hackathon, you don’t have to submit a fully flushed out 100% complete program for the contest, the idea is to do something quick and easy, and also innovative.
So get going, the Hackathon is in full swing!