Products

Solutions

Resources

Partners

Community

Blog

About

QA

Ideas Test

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

Welcome to the DNN Community Forums, your preferred source of online community support for all things related to DNN.
In order to participate you must be a registered DNNizen

HomeHomeDevelopment and...Development and...DNN Platform (o...DNN Platform (o...DNN WebAPI Bug in multi portal context; source/ fix includedDNN WebAPI Bug in multi portal context; source/ fix included
Previous
 
Next
New Post
2/6/2015 3:17 PM
 

We found a bug within the WebAPI in the multi portal context: The WebAPI requires (as implemented today) a separation between portals within one DNN installation a different domain (host) per portal. So using the WebAPI doesn't make any problems if you use it within of one of several parent portals. However using the WebAPI within child portals doesn't work because of the missing possibility to separate this multiple child portals under one parent portal. You could say: using WebAPI in child portals is ugly. Ok, may be; but what about upgraded existing DNN installations.

So, here is what you need to change and where.

 

DotNetNuke.Web\Api\Internal\DnnContextMessageHandler.cs

Method: SetupPortalSettings(HttpRequestMessage request)

 

private static PortalSettings SetupPortalSettings(HttpRequestMessage request)

        {

            //hotfix ITM: 2015-02-06

            var portalId = -1;

            var queryStrings = request.GetQueryNameValuePairs();

            var match = queryStrings.FirstOrDefault(kv => System.String.Compare(kv.Key, "portalid", System.StringComparison.OrdinalIgnoreCase) == 0);

            if (!string.IsNullOrEmpty(match.Value))

            {

                Int32.TryParse(match.Value, out portalId);

            }

 

            if (portalId < 0)

            {

                var domainName = TestableGlobals.Instance.GetDomainName(request.RequestUri);

                var alias = PortalAliasController.Instance.GetPortalAlias(domainName);           

                portalId = alias.PortalID;

            }

 

            int tabId;

            ValidateTabAndModuleContext(request, portalId, out tabId);

            //hotfix end

            

            var portalSettings = new PortalSettings(portalId);

 

            request.GetHttpContext().Items["PortalSettings"] = portalSettings;

            return portalSettings;

        }

 

 

 

 

 

 
New Post
2/6/2015 5:00 PM
 
A small update to Benjamins post. We have create a complete solution for our portals that are all running in multiportal context since version 4.x. With every webapi call we provide the current portalId within the header data like it is done with moduleId and tabId.


DotNetNuke.Web\Api\Internal\DnnContextMessageHandler.cs:
private static PortalSettings SetupPortalSettings(HttpRequestMessage request)
        {
            //hotfix ITM: 2015-02-06
            var portalId = -1;
            IEnumerable<string> headerValues;
            var keyFound = request.Headers.TryGetValues("PortalId", out headerValues);
            if (keyFound)
            {
                Int32.TryParse(headerValues.FirstOrDefault(), out portalId); ;
            } 

            if (portalId < 0)
            {
                var domainName = TestableGlobals.Instance.GetDomainName(request.RequestUri);
                var alias = PortalAliasController.Instance.GetPortalAlias(domainName);           
                portalId = alias.PortalID;
            }

            int tabId;
            ValidateTabAndModuleContext(request, portalId, out tabId);
            //hotfix end
            
            var portalSettings = new PortalSettings(portalId);

            request.GetHttpContext().Items["PortalSettings"] = portalSettings;
            return portalSettings;
        }



...\Library\Framework\ServicesFrameworkImpl.cs:
public void RegisterAjaxScript(Page page)
        {
var path = ServicesFramework.GetServiceFrameworkRoot();
            if (String.IsNullOrEmpty(path))
            {
                return;
            }

            JavaScript.RegisterClientReference(page, ClientAPI.ClientNamespaceReferences.dnn);
            ClientAPI.RegisterClientVariable(page, "sf_siteRoot", path, /*overwrite*/ true);
            ClientAPI.RegisterClientVariable(page, "sf_tabId", PortalSettings.Current.ActiveTab.TabID.ToString(CultureInfo.InvariantCulture), /*overwrite*/ true);
            //hotfix ITM: 2015-02-06
            ClientAPI.RegisterClientVariable(page, "sf_portalId", PortalSettings.Current.PortalId.ToString(CultureInfo.InvariantCulture), /*overwrite*/ true);
            //hotfix end

.....

            }




js\dnn.servicesframework.js (here in pretty print)

(function ($) {
    $.dnnSF = function (moduleId) {
        var base = this;
        base.getServiceRoot = function (moduleName) {
            var serviceRoot = dnn.getVar("sf_siteRoot", "/");
            serviceRoot += "DesktopModules/" + moduleName + "/API/";
            return serviceRoot;
        };
        base.getTabId = function () {
            return dnn.getVar("sf_tabId", -1);
        };
        base.getModuleId = function () {
            return moduleId;
        };
        //hotfix ITM: 2015-02-06
        base.getPortalId = function() {
            return dnn.getVar("sf_portalId", -1);
        };
        //hotfix end
        base.setModuleHeaders = function (xhr) {
            var tabId = base.getTabId();
            if (tabId > -1) {
                xhr.setRequestHeader("ModuleId", base.getModuleId());
                xhr.setRequestHeader("TabId", tabId);
                //hotfix ITM: 2015-02-06
                xhr.setRequestHeader("PortalId", base.getPortalId());
                //hotfix end
            }
            var afValue = base.getAntiForgeryValue();
            if (afValue) {
                xhr.setRequestHeader("RequestVerificationToken", afValue);
            }
        };
        base.getAntiForgeryKey = function () {
            return "__RequestVerificationToken";
        };
        base.getAntiForgeryValue = function () {
            return $('[name="__RequestVerificationToken"]').val();
        };
        return base;
    };
    $.ServicesFramework = function (moduleId) {
        return new $.dnnSF(moduleId);
    };
})(jQuery);

 
New Post
2/7/2015 12:55 PM
 
please note, for suggested code enhancements/fixes the best approach is to create a jira at support.dnnsoftware.com and (if you have the time/capability) to consider creating a pull request - http://www.dnnsoftware.com/wiki/page/... . Please note, it would help to list the failing url(s), as I was under the impression that the API requests were portal-agnostic (i.e. they did not trigger a portal change and the subsequent change of security)

Buy the new Professional DNN7: Open Source .NET CMS Platform book Amazon US
 
New Post
2/9/2015 12:49 PM
 

Hey Cathal,

with a webapi call the SetupPortalSettings() is called to provide a portal context. As it is build by now there is the context from the root portal because of the orientation by the portal alias from the calling url. You're right to say that web api calls are portal agnostic. Web api calls are under direct path"dnnportal.com/desktopModules/...". Therefore there is no possibility to get the subportal context. This means that with every web api call you get the portal context of the root portal. If the calling user is not present in the root portal then you get an exception and the webapi call logs you out of the portal. This only happens if you have subportals under virtual directories like "dnnportal.com/uk" or "dnnportal.com/ie".

Best wishes

Steffen

p.s. I see what I can do to provide this by git. But I'm afraid it will take some time.

 
Previous
 
Next
HomeHomeDevelopment and...Development and...DNN Platform (o...DNN Platform (o...DNN WebAPI Bug in multi portal context; source/ fix includedDNN WebAPI Bug in multi portal context; source/ fix included


These Forums are dedicated to discussion of DNN Platform and Evoq Solutions.

For the benefit of the community and to protect the integrity of the ecosystem, please observe the following posting guidelines:

  1. No Advertising. This includes promotion of commercial and non-commercial products or services which are not directly related to DNN.
  2. No vendor trolling / poaching. If someone posts about a vendor issue, allow the vendor or other customers to respond. Any post that looks like trolling / poaching will be removed.
  3. Discussion or promotion of DNN Platform product releases under a different brand name are strictly prohibited.
  4. No Flaming or Trolling.
  5. No Profanity, Racism, or Prejudice.
  6. Site Moderators have the final word on approving / removing a thread or post or comment.
  7. English language posting only, please.
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out