Simple RESTful JSON web services with DotNetNuke

By: Chris Hammond Google+
Published Date 8/24/2010
Last Updated Thursday, October 10, 2013 11:59 AM

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!

Recent Comments

Chris, I tried installing and testing your services module and it appeared to have installed properly but the service URLS were not returning any data. Even the web.config had your entries in there yet nothing was happening when I hit those URLS. Any idea?
Posted By: Kevin Forte on Friday, November 08, 2013 11:37 PM
This blog post is rather old, and services in DNN are now done through the WebAPI approach. Check out http://dnnsimplearticle.codeplex.com for a working service example
Posted By: Chris Hammond on Friday, November 08, 2013 11:40 PM
Chris, I cannot see Web API examples in this project http://dnnsimplearticle.codeplex.com. Could you please advise? Thanks
Posted By: Jonathan Lie on Tuesday, November 12, 2013 3:26 AM
You'll want to check out the SERVICES folder https://dnnsimplearticle.codeplex.com/SourceControl/latest#cs/services/
Posted By: Chris Hammond on Tuesday, November 12, 2013 4:52 AM
wishing to see how to authinticate android user in dotnetnuke ??
Posted By: mohammad abdelrhaman on Friday, February 21, 2014 1:31 PM
Hello Chris, I tried your service module about a year ago with DNN 705 and it worked well and i created my own service module following same pattern. But now i have to create a new service module for DNN740 and for testing purpose i just tried previous service modules with DNN740 but its giving me 404 error. Please suggest me how to overcome with the issue . Thanks
Posted By: Ravindra Kumar on Thursday, October 08, 2015 1:45 PM

Add Comment

Please add your comment by filling out the field(s) below. Your comment may need to be approved before it becomes visible.
Enter your first name for display with the comment
Enter your last name for display with the comment.
Enter your email address so that we may contact you if necessary. We will also use this for your Gravatar.
Enter the URL to your website. URLs may be removed from comments.
Enter your comment here.
If you can't type Human in, you can't post, plain and simple.
Submit Comment Cancel

Chris Hammond is

Chris Hammond is a father, husband, leader, developer and car guy. Chris has long specialized in ASP.NET and DotNetNuke development, so you will find a variety of topics here on the website. For more information check out the about me page.

If you are looking for DotNetNuke consulting please visit my business website at http://www.christoc.com/

Disclaimer

Any blog posts here are solely the opinion and views of Chris Hammond only. Comments on blog posts are the opinion of the commenter, and not Chris Hammond.

Powered By

This website is managed by Christoc.com Software Solutions

DotNetNuke Hosting

Hosting for this website is provided by AppliedI.Net. Be sure to visit them for all your DotNetNuke Hosting needs. 

Find Me