en-CAfr-CA
 
     

Creating a webservice in DotNetNuke 7

Jun 11 2014

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, 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:

01.using System.Net;
02.using System.Net.Http;
03.using System.Web.Http;
04.using DotNetNuke.Web.Api;
05. 
06.namespace MyService
07.{
08.    public class PingController : DnnApiController
09.    {
10.        [AllowAnonymous]
11.        [HttpGet]
12.        public HttpResponseMessage PublicPing()
13.        {
14.            return Request.CreateResponse(HttpStatusCode.OK, "Pong!");
15.        }
16.    }
17. 
18.    public class RouteMapper : IServiceRouteMapper
19.    {
20.        public void RegisterRoutes(IMapRoute mapRouteManager)
21.        {
22.            mapRouteManager.MapHttpRoute("MyService", "default", "{controller}/{action}", new[]{"MyService"});
23.        }
24.    }
25.}
  1. We simply start with some using statements for our requirements as shown above
  2. 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.
  3. 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:
    1. 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.
    2. It must inherit DnnApiController so it will use the DotNetNuke Services Framework.
  4. 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.
  5. 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.

Ok 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.

For more information on the basics, see Getting Started with Services Framework WebAPI Edition blog post on DotNetNuke website.


Passing parameters

Ok, so 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):

01.public class UsersController : DnnApiController
02.    {
03.        [RequireHost]
04.        [HttpGet]
05.        public HttpResponseMessage GetEmail(int userid)
06.        {
07.            DotNetNuke.Entities.Users.UserInfo ui;
08.            ui = DotNetNuke.Entities.Users.UserController.GetUserById(PortalSettings.PortalId, userid);
09.            return Request.CreateResponse(HttpStatusCode.OK, ui.Email);
10.        }
11.    }
  1. 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.
  2. 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...
  3. 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.


Using HttpPost : (answer to a comment down bellow)

To answer Massod comment bellow, it is almost the same thing but you need to create an object to contain the posted data.

Let's make a simple ping that uses POST, first we need to create an object that will contain the posted data such as:
   

public class FormMessage
    {
        public string Message { get; set; }
    }


Then we create the service method something like this:
public class PingController : DnnApiController
   {
       [AllowAnonymous]
       [HttpPost]
       public HttpResponseMessage PostPing(FormMessage formMessage)
       {
           return Request.CreateResponse(HttpStatusCode.OK, "Pong from POST: message was '" + formMessage.Message + "'.");
       }
   }

note that normally, a post would only return ok and no message, I am just doing this so we can test here.

Now since this is a POST verb, we can't test it by only using url parameters, we need to make an html file with a form to test it out. It would be someting like this:
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
    <title>Untitled Pagetitle>
head>
<body>
    <form action="http://dnndev/DesktopModules/MyService/API/Ping/PostPing" method="POST">
        <label for="message">Message: label><input type="text" name="Message"/>
        <input type="submit" value="Submit"/>
    form>
body>
html>

The important thing to not here is that you can't just create your POST method taking a string even if this is only what you need, you do need to create an object that will take your parameters.

Also don't forget that this is only for testing, you usually don't want to make this publicly available, you would normally use another parameter than [AllowAnonymous] such as  [DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)] and [ValidateAntiForgeryToken] unless you really want that to be public.

Let me know if you have any more questions...

At a comment below, you can now download the project files here. Please note however that you will have to update the project references to your local .dll files.

Total: 4 Comment(s)
Abbas Electricwala
  I created a simple class library, added all references as specified in the article, also configured the output path as the DNN7's bin directory, but i am unable to access Dotnetnuke.Web.Api namespace, can you please advice which assembly i am missing, below are the assemblies i am referencing: 1. DotNetNuke 2. DotNetNuke.Web. 3. DotNetNuke.Web.Client 4. System.Web. 5. System.Net. 6. System.Net.Http. 7. System.Net.Http.Formatting
· reply · 0 0 0
Daniel Valadas
Daniel Valadas  Hi, the DotNetNuke.Web.Api is in the dotnetnuke.web.dll assembly. Are you sure you have referenced the assembly from a recent DotNetNuke version?
· reply · 0 0 0
Rodrigo
  Hi, A link to download the project files would be nice. Thanks
· reply · 0 0 0
Daniel Valadas
Daniel Valadas  I have added the project files at the end of the post.
· reply · 0 0 0

Author

Daniel Valadas 10125 9

Calendar

2018 Jul 5 1
2018 Jun 12 1
2018 May 25 1
2014 Oct 525 3
2014 Jun 4793 1
2014 Feb 3288 1
2012 Mar 1477 1

Recent Posts

Core modules development team first meeting recording
2018-07-06 12:53 PM | Daniel Valadas
Removing Roadblocks to Upgrading By Reviving the Old Core Modules
2018-06-25 4:23 PM | Daniel Valadas
How to secure a whole Dnn site with an SSL certificate
2018-05-08 4:51 PM | Daniel Valadas
Take a list of emails and separate them with a semi-colon (;)
2014-10-24 5:14 AM | Daniel Valadas
Fix: DotNetNuke users can't reset their password
2014-10-24 3:21 AM | Daniel Valadas
Fixing duplicate Display Names in DotNetNuke
2014-10-19 11:17 PM | Daniel Valadas
Creating a webservice in DotNetNuke 7
2014-06-11 1:02 PM | Daniel Valadas
How to move a DotNetNuke Website to another server
2014-02-10 10:51 AM | Daniel Valadas
World Backup Day
2012-03-31 1:28 PM | Daniel Valadas