I have recently been assigned to built a DotNetNuke web service to allow a windows application (or any type of web client for that matter) the ability to manage DotNetNuke user accounts (create, change roles, delete, retrieve email address, etc.). Since I had a hard time finding a correct code sample or documentation that actually applies to DotNetNuke 7 and accessing it without being previously logged in to DotNetNuke 7 Hosting, it was difficult to built anything. I finally found out how to do it correctly so I tough I would put my efforts to some use and write a blog post explaining how to do it step by step.

The basics

That said, let's begin by the basics and just make a publicly accessible web service that allows anyone to ping the web service and get a pong back. For that we will use the new DotNetNuke 7 Services Framework which makes it quite simple if you know how to use it. In order to make a web service that will work withing DotNetNuke 7, you will need to fire up Visual Studio and create a Class Library project (c# or VB but all examples here will be in c#). That done, we will then reference some required DotNetNuke 7 required libraries (using the Add Reference dialog box), here's the list:

DotNetNuke.dll

DotNetNuke.Web.dll

System.Net.Http.dll

System.Net.Http.Formatting.dll

System.Web.Http.dll

Then we also need to reference the System.Web class from the .NET tab of the same dialog box. Finally, we neet to set the output path of the project to the DotNetNuke bin directory and we are ready to code. Here is the code, the explanations follow:

using System.Net;

using System.Net.Http;

using System.Web.Http;

using DotNetNuke.Web.Api;

namespace MyService

{

public class PingController : DnnApiController

{

 [AllowAnonymous]

 [HttpGet]

public HttpResponseMessage PublicPing()

{

return Request.CreateResponse(HttpStatusCode.OK, "Pong!");

}

}

public class RouteMapper : IServiceRouteMapper

{

public void RegisterRoutes(IMapRoute mapRouteManager)

{

mapRouteManager.MapHttpRoute("MyService", "default", "{controller}/{action}", new[]{"MyService"});

}

}

}

We simply start with some using statements for our requirements as shown above. We create a namespace for our service and whatever name we use here will be part of the url. I used MyService just for this example but use any name that makes sense for your service. Now we create a public class for our controller. You can create multiple controllers if you need to and the controller is just a group of related actions that make sense to group together. In my real project I have a PingController for testing purposes, a UsersController for any actions that relate to user accounts etc. Just use a name that makes sense since it will also show up in the url. Two things to be careful here:

The name of your controller must end with the word Controller but only what comes before it will show in the url, so for PingController, only Ping will show in the url path.

It must inherit DnnApiController so it will use the DotNetNuke Services Framework.

Then we create the actual action, in our case, PublicPing. It is just a simple method which return an HttpResponseMessage and can have a few attributes. By default the new services framework will respond only to host users and you need to explicitly allow other access rights if needed, in this case the [AllowAnonymous] makes this method (or action if you prefer) available to anyone without credentials. The second attribute, [HttpGet] will make this action respond to HTTP GET verb, which is usually used when requesting some date from the web server.

Finally in that action, you insert whatever code you action needs to do, in this case just return the string "Pong!", just remember that you need to return an HttpResponseMessage and not a string or int or other object. So, our controller and action is done, now we just need to map that to an actual URL and that what the last part of the previous code does. In essence this code tells DotNetNuke to map a certain url pattern to the methods defined in your class. You can use that code as is just replacing MyService by whatever your service name is.

Testing:
That's all there is to it, your service is ready!  To test it, first compile it, then just navigate to http://yourdomain/DesktopModules/MyService/API/Ping/PublicPing and you should see "Pong!" in your browser as a response.

Passing parameters

The basic code above is working but it doesn't do anything useful. Lets add something more useful by creating an action that will give us the email address for a specific user id.

Again, here's the code and the explanations will follow (place the code inside the same namespace as the previous one):

public class UsersController : DnnApiController

{

[RequireHost]

[HttpGet]

public HttpResponseMessage GetEmail(int userid)

{

DotNetNuke.Entities.Users.UserInfo ui;

ui = DotNetNuke.Entities.Users.UserController.GetUserById(PortalSettings.PortalId, userid);

return Request.CreateResponse(HttpStatusCode.OK, ui.Email);

}

}

First we build a UsersController class that will hold all actions related to user accounts, it is not absolutely necessary, you can have many actions in the same controller, however since this action is not at all related to our PingController, let'a make a new one more descriptive. We then make a GetEmail action (method) that will accept a userid parameter. The [RequireHost] parameter here will make it accessible only to host users, we'll see later other authentication options.

The code in the method itself is pretty much self explanatory. The only interesting thing to note here is that because our class inherits DnnApiController, we already have a PortalSettings object available. That's the big advantage of making use of the DotNetNuke Services Framework. You will have a ModuleInfo object to represent your module (if there is one with the same name as your service, which is not necessary such in this case), a PortalSettings object that represents the portal at the domain name used to access the service (portal alias) and finally a UserInfo object representing the user that accessed the web service.

Testing:
If we now navigate to http://yourdomain/MyService/API/Users/GetEmail?userid=2 you should receive the email address back from the server unless of course that userid does not exist, make sure to test with a userid that actually exists for that portal. If you where not previously connected with a host account, then you will be asked for credentials.

Limiting access to certain roles

Ok, that works but you need to give host credentials to any person needing to use your webservice. To avoid that you can replace [RequireHost] by [DnnAuthorize(StaticRoles="Administrators")] which will limit access to administrators. Better but you still need to give them an admin account. So the easy way to give only limited access would be to create a new role in DotNetNuke just for your web service and replace Administrators by that specific role name in the authentication parameter.