DNN Blog

Getting Started with DotNetNuke Services Framework

by Scott S on Monday, March 19, 2012 4:34 PM

(May 22, 2012 updated to reflect the RTM of 6.2.0)

In 6.2 DotNetNuke is beginning a framework for creating web services that are tightly integrated in the DotNetNuke platform.  Below is a Hello World example using this new framework.  Keep watching this blog for a deeper look at the features of the Services Framework.

Creating a web service with the Services Framework is very easy.  Before you start, ensure you have installed the 6.2.0 RC or the final release when it is available.

The next step is to setup a new class library project with references to all the appropriate libraries.

  1. In Visual Studio create a new class library project for .Net Framework 3.5.0
  2. Add references to the following libraries in your installation (Browse to the /bin folder of your install using the Add Reference dialog box)
    1. DotNetNuke.dll
    2. DotNetNuke.Web.dll
    3. System.Web.Mvc.dll
  3. Add references to the following standard .Net libraries (Use the .Net tab of the Add Reference dialog box)
    1. System.Web.Abstractions
    2. System.Web.Routing
  4. Set the output path of your project to the /bin folder of you 6.2.0 installation.
  5. Delete the default Class1.cs file

Now you are ready to write your own controller, add a new class with the following code:

using DotNetNuke.Web.Services; 

namespace HelloWorldServices 
{ 
    public class WelcomeController : DnnController 
    { 
        [DnnAuthorize(AllowAnonymous = true)] 
        public string HelloWorld() 
        { 
            return "Hello World!"; 
        } 
    } 
} 

The first important detail in this code snippet is the class name.  ASP.Net MVC requires that the name of all controllers end with the word Controller hence the name of our class WelcomeController.  Without the word Controller at the end of the name the service will not work.

The next important detail is that we have inherited from DnnController.  This is very similar to the Asp.Net MVC Controller class but adds the various DotNetNuke framework integrations such as authentication, and access to the portal settings.

The final important detail is the use of the DnnAuthorize attribute.  Authorization is one area where the DotNetNuke Services Framework deviates substantially from ASP.Net MVC.  A standard ASP.Net MVC application essentially leaves all methods open to anonymous access by default, and then various Auth filters are applied to tighten that access where needed.  DotNetNuke has taken the opposite approach, by default all methods require Host level authorization, and then various Auth filters are appiled to loosen that access where needed.  In this case we want to allow anonymous access to our HelloWorld service.

The service itself is pretty simple, the only remaining question is what URL to use to call this service.  Those familiar with ASP.Net MVC will know that you must setup a route to make the methods on your controllers accessible to the web.  Create another class and insert the following code:

using DotNetNuke.Web.Services;
namespace HelloWorldServices
{
    public class MyServicesRouteMapper : IServiceRouteMapper
    {
        public void RegisterRoutes(IMapRoute routeManager)
        {
            routeManager.MapRoute("MyServices", "{controller}/{action}", new[] {"HelloWorldServices"});
        }
    }
}

Traditionally routing is done inside Global.asax. It would be very messy to update Global.asax for every service installed in a DotNetNuke site so instead we created the IServiceRoutMapper interface.  This interface allows you to register routes in a fashion very similar to ASP.Net MVC.  All routes for the services framework will be mapped to the following structure:

~/DesktopModules/<moduleFolderName>/API/<url>

Here is a break down of each of the parameters passed to IMapRoute.MapRoute:

“MyServices” – string moduleFolderName: Unique to DNN this parameter should be a name unique to your module/service, and will typically match the name of the DesktopModules folder in which your module is installed.  It is important to use a name unique to your service to avoid routing conflicts with other services that may be installed.

“{controller}/{action}” – string url: Standard ASP.Net MVC parameter that defines the unique characteristics of your route.

new[] {“HelloWorldServices”} – string[] namespaces: This is an optional ASP.Net MVC parameter that is required for DotNetNuke Services Framework.  An array of namespaces to search for controllers for this route.  This parameter helps prevent conflict between services built by different developers.

If you have been paying close attention you will notice that we no longer include a name parameter in the MapRoute method.  In some configurations it is necessary to create several RouteTable entries for each logical route, making it impossible to use the name parameter exactly as specified.  Instead the route name is based on the moduleFolderName parameter.  In the rare instance that the actual name for a route is needed, it can be found in the DataTokens dictionary on the returned Route object by using the key “name”.

Now compile the code and all that remains to do is to test your service.  There is no installation or registration required for services framework, as long as the .dll is present in the /bin folder the service will be setup when the site starts.  See step 4 above if the .dll is not in the website’s /bin folder after compilation.

To test the service simply open a browser to ~/DesktopModules/MyServices/API/Welcome/HelloWorld and your browser should load a page that says "Hello World!". Because service routes are only mapped when DotNetNuke starts up you may need to recycle the application pool if your site was already running before you compiled your service.

That is all there is to building a basic service using the DotNetNuke Services Framework.

In 6.2.0 we have focused on providing tight integration with the DotNetNuke authentication and module permissions which allow you to easily create the services to power an Ajax based UI.  Stay tuned for more posts with all the details...

Scott Schlesier
Author

Interesting things I encounter as a software engineer on the DotNetNuke Corp. development team.

45 comment(s) so far...

Alex Shirley 3/21/2012

Big "like" here!<br /><br />Does this mean people will be converting their entity framework apps to work through this interface instead just to access the DNN security model?<br /><br />Wondering what the Pros vs the cons when using this vs Entity framework (e.g. see Steve Fabians blog). Is it all about security? Performance maybe? The choices of technology to use in order to implement client side code (i.e. XML services to be consumed across multiple devices perhaps) is becoming more and more mind boggling.<br /><br />Look forward to the next post...!<br /><br />Cheers<br /><br />Alex

 
Peter Donker 3/21/2012

There's no need for entity framework here. It is unrelated to this service framework. You can if you want, but it is not part of this.<br /><br />Peter

 
Steven Webster 3/21/2012

I like this direction as well. A few use cases might help people understand how to incorporate this into their plans. If I understand this correctly this means we could write role secured services that return jason, xml, etc. Perhaps for use with a module, external application or mobile hybrid code framework like Sencha or JQMobile?

 
cathal connolly 3/22/2012

@Steven Webster - yes, the services are accessed via standard http requests so anything that talks http can use them (e.g. javascript ajax requests, other modules, mobile clients etc.)-all the services that we've added to 6.2.0 return json but individual services can decide what format(s) they will return

 
Stephan Snoek 3/23/2012

This is great! integrated security and no need to make any changes to the web.config. This will make it easy to implement services into re-usable module controls.

 
Alex Shirley 3/26/2012

Opps I should have said MVC rather than entity framework Peter - sorry!<br /><br />This is a nice little demo that works straight away... thanks for this Scott.<br />On to Peter's blog now...

 
Scott S 3/26/2012

@Alex, I doubt anyone would convert their MVC app to webforms, but the service framework would make it very easy to call from the MVC app to their DNN site.<br /><br />I have drafted a post giving a better overview of Services Framework and where it is today and where we are hoping to take it tomorrow. It should be up in the next couple of days and should answer many questions.

 
Alex Shirley 3/27/2012

Nice one Scott - thankyou...

 
Fabio Parigi 5/22/2012

Hi Scott <br />tryed but I can't compile<br />i have this error:<br />Error 1 The type or namespace name 'ServicesRoutingManager' could not be found (are you missing a using directive or an assembly reference?) C:\Progetti\xx\DNNUserTest\UserIntegration\ServiceController.cs 14 30 UserIntegration<br /><br />I have a problem for the mapping, can you help me?<br />thanks

 
Scott S 5/22/2012

@Rmartin, <br /><br />The above code worked with CTP2, but some of the type names were changed and re-organized after that. RegisterRoutes now takes an IMapRoute object.<br /><br />Now that 6.2 is wrapping up, and leading up to DoDNN Charlotte I will be updating this post with code that works on RTM, and finally getting out a post with more meat on it.

 
Fabio Parigi 5/23/2012

Hi Scott <br />now it work thanks a lot!!!!

 
jhoy 6/12/2012

Hey Scott,

You stated above, "All routes for the services framework will be mapped to the following structure: ~/DesktopModules//API/"

Am I to understand that any services added to DNN using this framework MUST be associated with a module? I would like to create a service that is available from anywhere and not associated with any particular module. Can I place my code somewhere outside of the DesktopModules folder and still utilize the new framework?

For instance, I am currently working on a module to fetch and display videos which are hosted by a third party (VBrick). I want the ability to make requests via Javascript/JQuery to retrieve embed codes and SEO meta data for our collection of videos. In order to do this, I need a proxy service because browsers will not allow cross-server scripting due to the associated security risks. I would like to set up the proxy service in a way which would allow me to make requests to it from any module, or even from another web application running on the same server if I so choose. Since I do not want the service to be associated with any particular module, I see no reason for it to be housed in the ~/DesktopModules folder, and I would like to place it (and any future services that I develop) in another location. Is this possible?

 
Scott S 6/25/2012

@jhoy the path to the service MUST ALWAYS be ~/DesktopModules/ModuleName/API, this helps ensure that the service paths do not conflict with other paths setup by the CMS features of DNN. The path requirement in no way requires all the callers to be part of the same module (there are optional AuthFilters to require this), and in fact ModuleName does not even have to be a real module, though I recommend thinking carefully about why it is important that ModuleName is not a real module before choosing to take that approach.

 
Praveen Kumar 6/28/2012

Hi Scott,

Is this code will work for MVC 2.0 Application?
If yes then what steps should be taken for routing.

Many-2 thanks to you in advance

 
Scott S 6/29/2012

@Praveen this code must run as part of a DotNetNuke site. Anything derived from DnnController will not work properly outside of a DotNetNuke site.

 
alex b 6/30/2012

Hello, can't figure out the URL for this service, i am using:
http://localhost:38625/DesctopModules/DnnHello/API/WelcomeController/HelloWorld

 
Scott S 7/3/2012

@alex b

Service Framework urls are in the form ~/DesktopModules//API/

In this case the moduleFolderName is registered as MyServices, the controller is named WelcomeController and the action is HelloWorld all of which leads to:

~/DesktopModules/MyServices/API/Welcome/HelloWorld

as the correct url.

 
Fabio Parigi 7/13/2012

Hi Scott S
I have a big big problem, In a new installation of DNN the Service framework go well, I have an old version I think from 2009 It ll be DNN 4.9 that I have made a lot of uprade in this last 3 years, now the system is at the 6.2.1 version but the example like your return 404.
On a new installation HelloWorldService work well?

I think that the path is not recognized like a MVC call
What I can to change or enable or delete for solve my problem
thanks a lot

Fabio

 
Scott S 7/13/2012

@Fabio, I have not heard of an upgrade not working though I suppose it is possible. Can you send a message using the internal messaging of 6.2, or post an item to the Journal? Those both use services framework, if they work then SF is generally working and the problem is more specific to your module.

 
Jim Frenette 8/7/2012

I am confused. Since the ServiceFramework URL is virtual, i.e., ~/DesktopModules/MyServices/API/Welcome/HelloWorld it can only be requested from within the DNN site, correct? Can you provide an end to end example of this? I want to figure out how to make the request from an MVC app that will be on the same or another server within the host domain

 
Scott S 8/7/2012

Jim, the URLs are virtual in that they don't refer to any real physical files or folders on the server. The URLs are however very "real", any HTTP request from any source made to the URL will generate an appropriate response.

 
nolan.sipos 8/10/2012

Hi Scott,

I've been plugging away at this, but not sure what the issue might be.

URL https://oms/~/DesktopModules/MyServices/API/Welcome/HelloWorld">https://oms/~/DesktopModules/MyServices/API/Welcome/HelloWorld />
tried also just to check https://oms/~/DesktopModules/MyServices/API/Welcome/HelloWorld">https://oms/~/DesktopModules/MyServices/API/Welcome/HelloWorld />
I always get a 404 error. There's really not much to your post for me to get wrong, so I'm not sure what's going on.

Any Ideas?

 
nolan.sipos 8/10/2012

Hi Scott,

Well I just posted but it doesn't appear to have shown up.

Is https://oms/~/DesktopModules/MyServices/API/Welcome/HelloWorld the correct format

or should it be

https://oms/DesktopModules/MyServices/API/Welcome/HelloWorld

or even

https://oms/default.aspx/~/DesktopModules/MyServices/API/Welcome/HelloWorld

Just can't seem to get this up and running for what ever reason as I always get a 404 when I try and navigate. At least some type of error other than 404 would probably go a ways to me figuring it out.

 
nolan.sipos 8/10/2012

Also Scott, I'm unsure if I'm missing some steps.

You said create a class library, is that supposed to be part of an MVC project? Or is this simply a stand alone library. So no use use of the actual Model/View/Controller setup that you have usually.

I'm waiting for the penny to drop, but it's just not happening.

Thanks for your help.

 
Scott S 8/10/2012

Nolan,

I suspect the problem is the tilde '~' character in your url. In the blog post I meant the tilde to represent the site root as it often does in asp.net URLs. https://oms/DesktopModules/MyServices/API/Welcome/HelloWorld is likely what you need.

Any project that references the correct dependencies will work, except possibly executables. I chose class library because it is the simplest of the projects. Starting with an MVC project would likely be a waste as you won't need the majority of template items that it includes by default.

 
Berney Villers 8/19/2012

I have long relied on iWeb for its simplicity and ease of use. IWeb has not been updated in years and it doesn't appear that it will be. Is there any guidance for the many people using iWeb to convert over to this approach and make web services that can be utilized from within other .Net applicaitons?

 
Scott S 8/20/2012

Berney, having never written anything with IWeb I'm no expert. After looking over the tutorials I would say that for the most part you need only move the code which fetches/processes the data in you IWeb service into an action in you Service Framework controller. If the IWeb service was returning SOAP, you will be much better off switching to JSON or XML or something more natural to Services Framework. Finally you need to update your client to ensure it calls the correct URL, in many cases it may be unchanged, but with Services Framework the child portion of a child portal URL will need to be included before DesktopMoules.

 
Jim Frenette 8/24/2012

Thanks Scott, I think I know why I am getting 404, do these classes should be part of a DNN module? That is what it looks like according to this resource: http://garvincasimir.wordpress.com/2012/03/26/dotnetnuke-services-framework-and-ajaxweblinks/

 
Scott S 8/24/2012

Jim, the classes should be in an assembly in the bin/ folder. I have heard the code will also work from app_code, but I have not tried it myself.

 
Jim Frenette 8/27/2012

Thanks Scott, Yes, my build output has always targeted the root dnn bin folder per your tutorial. I just can't get this simple HelloWorld to resolve... always a 404 no matter what I try. iisrest, restart dnn, etc. all after verify that the build is present/updated.

 
 
Scott S 8/28/2012

Jim,

Are you using IIS6 or a classic pipeline? If so change your route to {controller}.ashx/{action} and then use the url:

http://dnn6/DesktopModules/MyServices/API/Welcome.ashx/HelloWorld

This will force your request into the managed request handler. As you can see it is the technique we used for all the built-in routes.

 
Jim Frenette 8/30/2012

Scott, Unfortunately I am still getting 404 despite all code looking good and build successful, in the root bin folder. IIS 7.5; app pool: .NET 4.0; managed pipeline: Integrated; Identity Network Service; everything else default. Thanks again for your guidance.

 
Rodney Joyce 9/2/2012

WRT the 404 error - are you perhaps using Ifinity URL Master? http://www.ifinity.com.au/Products/Support_Forums/forumid/8/postid/8358/scope/posts

 

Thanks Scott. You rock.
Kendo UI, here I come!

 
Jim Frenette 9/4/2012

Rodney, I am using a default/fresh install of DotNetNuke CE 06.02.02 installed to a Windows 7 workstation for testing/development. Not using Ifinity URL Master. Thanks for the message.

 
Han 9/7/2012

Scott:

I followed your example word for word (copy-and-paste your code) and am also getting 404 error on my local dev machine (Win7 Pro, VS 10 dev web server, DNN 6.2.1). I googled around and couldn't find a lot on this. Maybe there's only a few of us having this problem, which means there may be some config on my machine not set up properly.

Jim:

Have you had any luck on fixing it?

-Han

 
Scott S 9/7/2012

Han, Jim,

I am at a loss as to what is causing your problems. In 6.2 several features depend on the Services Framework, and so far we have no reports of them failing due to Services Framework problems. Can you try sending a message through the message system or posting to a Journal. Both of those require the Service Framework to function.

 
 
Jim Frenette 9/10/2012

Thanks Han, The web.config change you documented did the trick for me.Updating my DNN web.config allowed http://dnn6/DesktopModules/MyServices/API/Welcome/HelloWorld to return the "Hello World!" response.






 
Scott S 9/10/2012

Hmmm, I have yet to find any environment where the preCondition on UrlRoutingModule-4.0 is required for the MVC version of Services Framework. However we did find this to be neccesary for WebAPI, and the changes are already part of the 7.0 CTP.

 
Glen Doecke 9/19/2012

Yes, Han's web.config change solved our problems as well. The problem didn't exist on the local laptop that it was coded on (using IISExpress7.5 in 4.0 app pool) but would not work on the 6.2.3 out of the box install on our real servers until those web.config changes were applied.

2ic

 
jhoy 11/15/2012

Great post, Scott, but I have a question about how to add some 'documentation' to my web services. If I try to add a web reference in a visual studio project, and provide the service URL (/DesktopModules/PWServices/API/Users/), I always get a 404 response. How can I make my services generate a response that describes the services themselves?

I'm relatively new to web services, but I am familiar with the concept of a WSDL...this is the sort of functionality I am aiming for.

 
Scott S 11/15/2012

There is no WSDL or anything similar to bind to. You could write your own WSDL I suppose, but there is nothing that will help you to create one. The services framework takes what I believe is the now predominant approach and encourages lightweight HTTP and REST style services. Calling these services is meant to be simple and work from any device that speaks HTTP. There is no ceremony or complicated contract. It should make little difference if you are using javascript in the browser, or node, or a device, or using objective-C, or using c#, or using a bash script with curl or .... All you need to know is the HTTP verb, and how to send parameters (in body, headers, or query string). When WSDL works it is quick and painless, but many environments that speak HTTP have no use for WSDL.

 
Scott McCulloch 4 months ago

This post should have a disclaimer message pointing to the DNN 7 changes.

Attend A Webinar
Start  Professional Edition Trial
Have Someone Contact Me

Like Us on Facebook Join our Network on LinkedIn Follow DNN Corporate on Twitter Follow DNN on Twitter

Advertisers

Sponsors

DotNetNuke Corporation

DotNetNuke (DNN) provides a suite of solutions that make designing, building and managing feature-rich sites and communities fast, easy and cost-effective. The DotNetNuke Platform CMS is the foundation for more than one million websites worldwide. DNN Social, our newest solution, enables businesses to create immersive, interactive communities. Thousands of organizations like True Value Hardware, Bose, Cornell University, Glacier Water, Dannon, Delphi, USAA, NASCAR, Northern Health and the City of Denver have leveraged DNN to deploy highly engaging business- critical websites. Our rapid growth in product sales and deployments resulted in DotNetNuke Corp. being named one of the fastest growing private companies in America by Inc. Magazine in 2011 and 2012.