1

I have a custom module I am developing in 7.3.4 platform. I have the ModuleSearchBase working in my development installation where I Overrride the GetModifiedSearchDocuments function to generate the search documents for the module.

The problem appears when I install this module in a "live" dnn installation.

Here is the stack trace that gets logged when the Search Index scheduled event runs:

DefaultDataProvider:DotNetNuke.Data.SqlDataProvider, DotNetNuke
ExceptionGUID:72337bbc-1a23-4103-bad9-70cbdb0e907d
InnerException:Value cannot be null. Parameter name: oldValue
FileName:
FileLineNumber:0
FileColumnNumber:0
Method:System.String.Replace
StackTrace:
Message:
System.ArgumentNullException: Value cannot be null.
Parameter name: oldValue
   at System.String.Replace(String oldValue, String newValue)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.GetFriendlyAlias(String path, String& httpAlias, Int32 portalId, FriendlyUrlSettings settings, PortalSettings portalSettings, Boolean& cultureSpecificAlias)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.FriendlyUrlInternal(TabInfo tab, String path, String pageName, String portalAlias, PortalSettings portalSettings)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.FriendlyUrl(TabInfo tab, String path, String pageName, PortalSettings portalSettings)
   at DotNetNuke.Services.Url.FriendlyUrl.DNNFriendlyUrlProvider.FriendlyUrl(TabInfo tab, String path, String pageName, PortalSettings settings)
   at DotNetNuke.Common.Globals.NavigateURL(Int32 tabID, Boolean isSuperTab, PortalSettings settings, String controlKey, String language, String pageName, String[] additionalParameters)
   at DotNetNuke.Common.Globals.NavigateURL(Int32 tabID, Boolean isSuperTab, PortalSettings settings, String controlKey, String language, String[] additionalParameters)
   at Krisis.Modules.KrisisStore.Components.FeatureController.GetModifiedSearchDocuments(ModuleInfo moduleInfo, DateTime beginDate)

What I tried:

  1. To me this looks like I had an error during a string replace function in the GetModifiedSearchDocuments. So I removed the two replace functions I was using and reinstalled it. THis error appeared exactly the same way.

  2. I tried to add some breakpoint VIA logging to the event viewer to see how far my code would execute before this error gets thrown. This allowed me to narrow down the error to the following line:

                    objEventLog.AddLog("BREAK 2", " break 2 " + ModID.ToString, pSettings, -1, DotNetNuke.Services.Log.EventLog.EventLogController.EventLogType.ADMIN_ALERT)
    
                    Dim DetailUrl = NavigateURL(moduleInfo.TabID, pSettings, "Detail", array)
    
                    objEventLog.AddLog("BREAK 3", "DetailUrl = " + DetailUrl, pSettings, -1, DotNetNuke.Services.Log.EventLog.EventLogController.EventLogType.ADMIN_ALERT)
    

You can see the "breakpoints" in the objEventLog.AddLog function. Breakpoint 2 is hit and breakpoint 3 is not. The code is breaking on the NaviagteURL function.

I have confirmed that the tabId value is not null and this is the exact code I use in a web.api service in the module and it works fine. Also, this code works perfectly fine in my local installation.

I don't understand why a string.replace null exception for the oldValue is being thrown during the NaviagteURL value.

QUESTION:

Can someone help me figure out why this NavigateURL function is throwing a string.replace error?

Thanks in advance

Edit 1:

I found This post and This JIRA issue that are related. It has to do with search not working if a primary portal alias has not been set. In this case it has been set and this issue seems to have been fixed in a previous version to the one I am running so I don't think this is it.

EDIT 2: SOLUTION

When I create the portal settings object inside DNN 7's new search function GetModifiedSearchDocuments, it does not automatically populate the PortalAlias and PrimaryAlias properties of the PortalSettings Object.

So I create a PortalAliasController and manually get the portal alias and asign it tot he PortalSettings object.

It feels like I am doing something worng and that creating a new PortalSettingsObject(portalID) should perform this task for me. I looked into the source code on gitHub and it seems like it should. But in my case it is not.

So the following code is what I used to pet a complete portal settings object so I can use the NavigateURL function without error:

        Public Overrides Function GetModifiedSearchDocuments(moduleInfo As ModuleInfo, beginDate As Date) As IList(Of Entities.SearchDocument)
        Try

            Dim SearchDocuments As New List(Of Entities.SearchDocument)

            'get list of changed products
            Dim vc As New ViewsController

            Dim pList As List(Of vw_ProductList_Short_Active) = vc.GetProduct_Short_Active(moduleInfo.PortalID)

            Dim pSettings As New PortalSettings(moduleInfo.PortalID)

            ''use portal alias controller to get primary portal alias of current portal
            Dim pac As New PortalAliasController
            Dim pAlias As PortalAliasInfo = TryCast(pac.GetPortalAliasesByPortalId(moduleInfo.PortalID).Where(Function(a) a.IsPrimary).Single, PortalAliasInfo)
            pSettings.PortalAlias = pAlias
            pSettings.PrimaryAlias = pAlias

            If pList IsNot Nothing Then
                ''for each product, create a searchdocument
                For Each p As vw_ProductList_Short_Active In pList


                    ''format parapeter array for detail url
                    Dim array() As String = {"mid=" + ModID.ToString, "id=" + p.ProductId.ToString, "item=" + p.Name.Replace(" ", "-")}

                    ''format detail url for search item
                    Dim DetailUrl As String = NavigateURL(moduleInfo.TabID, pSettings, "Detail", array)
                    Dim portalAlias As String = pSettings.DefaultPortalAlias
                    DetailUrl = DetailUrl.Replace("///", "//" + portalAlias + "/")
                    ''loop business logic cut out for brevity
                    With SearchDoc
                        .AuthorUserId = p.CreatedByUserId
                        .Body = p.ShortInfo
                        .Description = p.LongInfo
                        .IsActive = True
                        .PortalId = p.PortalId
                        .ModifiedTimeUtc = p.LastUpdatedDate
                        .Title = p.Name + " - " + p.ProductNumber
                        .UniqueKey = Guid.NewGuid().ToString()
                        .Url = DetailUrl
                        .ModuleId = p.ModuleId
                        .ModuleDefId = moduleInfo.ModuleDefID                            
                    End With

                    SearchDocuments.Add(SearchDoc)
                Next

                Return SearchDocuments

            Else
                Return Nothing
            End If

        Catch ex As Exception
            LogException(ex)
            Return Nothing
        End Try

    End Function
J King
  • 4,108
  • 10
  • 53
  • 103

1 Answers1

1

The only String.Replace in DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.GetFriendlyAlias() that the error could come from is line #571:

friendlyPath = friendlyPath.Replace(Globals.AddHTTP(httpAlias), String.Empty);

The httpAlias string is passed in from the outer function: DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.FriendlyUrl(). And this should have came from a core function that returns the portal's alias.

Check to see if you have a record in the PortalSettings table with SettingName = "DefaultPortalAlias" and the correct value. Also check if your PortalAlias table has the correct HttpAlias value for your portal and one record per portalID has IsPrimary flag set to true.

Fix It Scotty
  • 2,852
  • 11
  • 12
  • thanks, I have not been able to look into this much. I think I have a problem with the way I create a portalSettings object. Once I figure out more ill post back here. – J King Dec 19 '14 at 03:59
  • Okay, default portal alias is correctly set in the portal settings table and it is set as the primary alias and the alias settings are set to redirect. Still cant find what is happening – J King Dec 22 '14 at 04:24
  • It looks like the problem is because I am using the PortalSettings inside GetModifiedSearchDocuments for the new DNN 7 search. The portalSettings object is empty when I call GetPortalSettings and therefore when I call NaviagteUrl and pass in the portal settings the alias is empty and this triggers the null exception down the call stack. I clearly do not have a complete grasp of the new search implementation. – J King Dec 22 '14 at 04:59
  • J King. Good to hear you fixed it. Just as a comparison, check out my free tutorial example on my site where I have a ModuleSearchBase implementation. http://www.dotnetnuclear.com/articles/tabid/88/ID/16/DNNCon-Session-Customizing-Your-DNN-Search-Results.aspx#Files – Fix It Scotty Dec 23 '14 at 14:18
  • Even though this is a long time later, I posted the solution (edit #2). I would be interested in your feed back as I had to manually assign the portal alias and primary alias properties of the PortalSettings object. Is this how it should work, or should the portal alias already be set when creating the portal settings object. As for the string replace error, it was because of the missing portal alias info. – J King Feb 28 '15 at 21:26
  • J King, I can't explain why the portalAlias isn't set properly in the Portal Settings object. But, If you check out my ModuleSearchBase implementation (link in the previous comment), you will see that I am setting the Url = "" when creating the SearchDocument. The reason is because if I set the TabId and PortalId attributes, DNN will automatically create the url when returning the results. You would only need to set the Url attribute of the SearchDocument if you are indexing content with an external Url. – Fix It Scotty Mar 01 '15 at 01:12