dnn 7+ search is not indexing custom module items - vb.net

I have a dnn 7.2.2 development site running under dnndev.me on my local machine. I have created a simple product catalogue module and am trying to integrate the new search for dnn 7.
Here is the implementation of ModuleSearchBase in my feature/business controller
Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Services.Exceptions
Imports DotNetNuke.Services.Search
Imports DotNetNuke.Common.Globals
Namespace Components
Public Class FeatureController
Inherits ModuleSearchBase
Implements IUpgradeable
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)
If pList IsNot Nothing Then
''for each product, create a searchdocument
For Each p As vw_ProductList_Short_Active In pList
Dim SearchDoc As New Entities.SearchDocument
Dim ModID As Integer = 0
If p.ModuleId Is Nothing OrElse p.ModuleId = 0 Then
ModID = moduleInfo.ModuleID
Else
ModID = p.ModuleId
End If
Dim array() As String = {"mid=" + ModID.ToString, "id=" + p.ProductId.ToString, "item=" + Replace(p.Name, " ", "-")}
Dim DetailUrl = NavigateURL(moduleInfo.TabID, GetPortalSettings(), "Detail", array)
With SearchDoc
.AuthorUserId = p.CreatedByUserId
.Body = p.ShortInfo
.Description = p.LongInfo
.IsActive = True
.PortalId = moduleInfo.PortalID
.ModifiedTimeUtc = p.LastUpdatedDate
.Title = p.Name + " - " + p.ProductNumber
.UniqueKey = Guid.NewGuid().ToString()
.Url = DetailUrl
.SearchTypeId = 2
.ModuleId = p.ModuleId
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
End Class
End Namespace
I cleared the site cache and then I manually started a search re-index. I can see from the host schedule history that the re-index is run and completes.
PROBLEM
None of the items in the above code are added to the index. I even used the Luke Inspector to look into the lucene index and that confirms that these items are not added.
QUESTION
I need help figuring out why these items are not getting added or I need help on how to debug the indexing to see if anything is going run during that process.
Thanks in Advance
JK
EDIT #1
I ran the following procedure in Sql Server to see if the module is even listed in the search modules:
exec GetSearchModules[PortalId]
The module in question does appear in this list. The indexing is called for the featureController, but the results are not added to the lucene index. Still need help.
EDIT #2
So I upgraded to 7.3.1 in the hopes that something during the installation would fix this issue. But it did not. The search documents are still getting created/ returned by the GetModifiedSearchDocuments function but the documents are not being added to the Lucene index and therefore do not appear in the search results.
EDIT #3
The break point is not getting hit like i thought after the upgrade, but I added a try catch to log exceptions and the following error log is getting created when I try to manually re-index (cleaned up to keep it short)
AssemblyVersion:7.3.1
PortalID:-1
PortalName:
DefaultDataProvider:DotNetNuke.Data.SqlDataProvider, DotNetNuke
ExceptionGUID:d0a443da-3d68-4b82-afb3-8c9183cf8424
InnerException:Sequence contains more than one matching element
Method:System.Linq.Enumerable.Single
StackTrace:
Message:
System.InvalidOperationException: Sequence contains more than one matching element
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
at DotNetNuke.Services.Scheduling.Scheduler.CoreScheduler.LoadQueueFromTimer()
at DotNetNuke.Services.Scheduling.Scheduler.CoreScheduler.Start()
Source:
Server Name: KING-PC
EDIT #4
Okay, I fixed the problem in edit three following This Disucssion on the DNN issue tracker, but still no items being added to the lucene index.
The breakpoint is hit, and once i leave the debugger running for a while i get the following error:
{"Exception of type 'Lucene.Net.Index.MergePolicy+MergeException' was
thrown."} {"Cannot overwrite:
C:\websites\dnndev.me\App_Data\Search\_1f0.fdt"}
Looks like a permission error. I'll see what I can work out

J King,
I just finished a series on DNNHero.com on Implementing Search in your Module. Parts 3 and 4 are implementing and debugging your ModuleSearchBase implementation.
EDIT: Remove your assignment to the SearchTypeId in your implementation
Also, here is a sample snippet to see how i am setting the attributes of the SearchDocument. Again, watch my video for a whole bunch of other potential pitfalls in the Search implementation.
SearchDocument doc = new SearchDocument
{
UniqueKey = String.Format("{0}_{1}_{2}",
moduleInfo.ModuleDefinition.DefinitionName, moduleInfo.PortalID, item.ItemId),
AuthorUserId = item.AssignedUserId,
ModifiedTimeUtc = item.LastModifiedOnDate.ToUniversalTime(),
Title = item.ItemName,
Body = item.ItemDescription,
Url = "",
CultureCode = "en-US",
Description = "DotNetNuclear Search Content Item",
IsActive = true,
ModuleDefId = moduleInfo.ModuleDefID,
ModuleId = item.ModuleId,
PortalId = moduleInfo.PortalID,
TabId = tab
};

Related

Janus GridEX - C# How to show multi-line header using columnsets at runtime?

I have already tried:
How to wrap header caption in Janus GridEx
and
https://www.c-sharpcorner.com/forums/table-column-set
and looked through Janus documentation at http://codelibraries.blogspot.com/search/label/Janus%20GridEX.
I have a business requirement to show wrapped column header. For example, if column header is:
This is column header
need to show
This is column
header
As it is right now (before I tried implementing code for this requirement), code looked like:
dgMulti.SetDataBinding(bulkTable, "")
dgMulti.RetrieveStructure()
Dim column As Janus.Windows.GridEX.GridEXColumn
For Each column In dgMulti.RootTable.Columns
column.Width = 150
Next
where bulkTable is a System.Data.DataTable object.
After visiting above links, I tried suggestions and used ColumnSets as shown below and added after above code:
Dim CSET As New Janus.Windows.GridEX.GridEXColumnSet()
CSET.Caption = "YourCaption"
CSET.HeaderAlignment = Janus.Windows.GridEX.TextAlignment.Center
CSET.ColumnCount = 2
CSET.Width = 150
CSET.Key = "YourCaptionKey"
' FOLLOWING LINE THROW ERROR
**CSET.Add(New Janus.Windows.GridEX.GridEXColumn(dgMulti.RootTable.Columns(0).Key, dgMulti.RootTable.Columns(0).ColumnType), 0, 1)
CSET.Add(New Janus.Windows.GridEX.GridEXColumn(dgMulti.RootTable.Columns(1).Key, dgMulti.RootTable.Columns(1).ColumnType), 0, 2)**
dgMulti.RootTable.ColumnSets.Add(CSET)
dgMulti.RootTable.ColumnSetHeaderLines = 2
dgMulti.RootTable.CellLayoutMode = Janus.Windows.GridEX.CellLayoutMode.UseColumnSets
Error: Operation is not valid due to the current state of the object.
Can you please help what I am missing? I believe I need to somehow link the columns with ColumnSets but how?
You don't need columnsets for this.
I can't get a deeplink to the janus forums thread with this answer, but here is the copy/pasted answer:
You can put a CR Character if you can determine where to wrap.
in e.g.
Column.Caption = Now.ToString("ddd" & vbCr & "d MMM");
You can see the janus support forums here: https://www.janusys.com. Click through to the Winforms GridEX forum, and use search phrase "wrap".
The website is basically unusable in Firefox, I fallback to Chrome to browse.
Dim CSET As New Janus.Windows.GridEX.GridEXColumnSet()
CSET.Caption = "YourCaption"
CSET.HeaderAlignment = Janus.Windows.GridEX.TextAlignment.Center
CSET.ColumnCount = 2
CSET.Width = 150
CSET.Key = "YourCaptionKey"
dgMulti.RootTable.ColumnSets.Add(CSET)
CSET.Add(dgMulti.RootTable.Columns.Add("Yourcolumnkey"), 0, 0)
CSET.Add(dgMulti.RootTable.Columns.Add("Yourcolumnkey"), 0, 1)
dgMulti.RootTable.ColumnSetHeaderLines = 2
dgMulti.RootTable.CellLayoutMode = Janus.Windows.GridEX.CellLayoutMode.UseColumnSets

Why is a DOORS Module sometimes null when trying to edit the Module via DXL?

I'm new to DXL programming language in IBM DOORS. However, I think I have managed to do many interesting things: create Modules, create Objects, create Links, delete Objects etc.
However, I have a very specific problem regarding "null" Modules. I've just written null between "" because the modules exist and they are referenced with a correct name.
When doing this:
Module m1 = edit("1. MY_MODULE", false)
save(m1)
close(m1)
An error like this appears:
enter image description here
You could not understand what does that mean as it is spanish. Basically states this: "Module null parameter in the first position of the argument." That means that the "m1" is null, as the parameter for save() method is null.
The point is that it is an error which appears only sometimes. It seems that the Module is null as it has been previously opened and DOORS does not close properly.
Is there any way, any method...whatever to avoid this error?
I assume that the script cannot find the module when another folder is active.
Try
Module m1 = edit ("/myproject/myfolder/mysubfolder/1. MY_MODULE", false)
There might be many reasons that the module can't be opened in edit mode. For example: User do not have write access OR Module is being used by other user, etc.
However, you can get around the error with the below code snippet:
Module m = edit('My_module', false)
if(!null m) {
//execute program
...
}
else {
//do something
}
I hope this helps.
How does your script work? do you open the same module again and again and sometimes get the error or do you open lots of modules and for some of them it works and for others it doesn't? In the latter case, perhaps you misspelled the path. You could add some sanity checks like
string fullPathToMod = "/myproject/myfolder.."
Item i = item fullPathToMod;
if null i then error "there is no item called " fullPathToMod
if "Module" != type i then error "there is an item, but it's not a module, it's a " type i
This is how the Code is structured:
void checkModule(string folderPath, string mName, Skip list, int listSize, int listLastIndex, string headers[], string heading[], string headerKey, bool uniqueKey, string combinedKey[]){
if (module mName){
Folder f = folder(folderPath)
current = f
Module m = edit(folderPath""mName, false)
current = m
Object o = first(m) // error sometimes: Se ha pasado un parametro Module null en una posición de argumento 1
if (o == null){
loadModule(m, list, listSize, listLastIndex, headers, heading)
} else {
updateModule(m, mName, list, listSize, listLastIndex, heading, headerKey, headers, uniqueKey, combinedKey)
save(m)
close(m)
}
if (lastError() != ""){
print "Error: " lastError() "\n"
}
} else {
print "No module " mName ".\n"
}
}
Exactly it breaks in line:
current = m
But as said, only sometimes, not always.
BTW, I'm executing this script via Batch, via Java code. One curious thing is that if I close DOORS, and execute the script it does execute correctly. It is as if it needs to be closed in order to edit modules correctly.
I pressume current can be used more than once with different types of Items. I guess it should not be wrong, but it breaks saying (more or less):
Null value passed to DXL commmand (current Module).
Obviously, it means that m is null, but I cannot see any reason for that.

EF Core - Select on Include and ThenInclude

I'm using EF Core 2.1 and i have a Model SettingInformation. The SettingInformation has a Property Setting As ICollection(Of Setting).
The Setting Property has several Properties like Client As Client, User as User and also Workspace As Workspace. It's a bit complicated. Please see the Attached Diagram-Image.
Model-Diagram(Part of it)
Now i have the problem, that i'd like to get the complete Information of a Settinginformation.
The following code i have to get all Informations of a SettingInformation
Public Async Function GetCompleteSettingInformations(settingInfoId As Integer) As Task(Of SettingInformation)
Dim q As IQueryable(Of SettingInformation) = GetSettingInfoDefaultQuery()
q = q.Where(Function(s) s.SettingInformationId = settingInfoId)
q = q.Include(Function(i) i.Settings).ThenInclude(Function(i) i.User) _
.Include(Function(i) i.Settings).ThenInclude(Function(i) i.Workspace) _
.Include(Function(i) i.Settings).ThenInclude(Function(i) i.Client) _
.Include(Function(i) i.Protocol)
Dim ret = Await q.SingleOrDefaultAsync
Return ret
End Function
OK, this code works, but now i'd like to refactor this, because for example, I do not need the UserImage or the 'FailedLogins' of User when the 'LinkedToUser' Property of 'Protocol' is not nothing.
What i needed:
The complete 'SettingInformation' - OK easy
The 'Settings' From 'SettingInformation' (ICollection) - OK i can get this with the Include but in 'Settings':
only the 'UserName', 'FirstName' and 'LastName' from 'User' if 'User' is not Nothing
only the 'ClientShortName' and 'ClientLongName' of 'LinkedToClient' if 'Client is not Nothing
only the 'WorkspaceName' and 'WorkspaceLocation' of 'Workspace' id the 'Workspace' is not Nothing.
I hope so here is anybody who can help me to optimize this Query because now i also cat for example the UserImage for each Setting and this results in a long loadingtime.
EDIT:
OK, now i have tried to do that with EagerLoading. But the Select is ignored. But why? the following code:
'Alle WorkspaceIDs ermitteln für welche es Settingmodifikationen gibt
Dim wsIds As List(Of Integer) = ret.Settings.Where(Function(u) u.WorkspaceId.HasValue).Select(Function(u) u.WorkspaceId.Value).ToList
Await ContextInternal.Workspaces.Where(Function(u) wsIds.Contains(u.WorkspaceId)) _
.Select(Function(su) New Workspace() With {.WorkspaceName = su.WorkspaceName, .WorkspaceLocation = su.WorkspaceLocation, .WorkspaceDesciption = su.WorkspaceDesciption, .WorkspaceId = su.WorkspaceId, .Settings = su.Settings}).AsTracking.LoadAsync
Loads all workspaces that are related in Protocols. I will only get the columns ID, Description, Location and Name. But i get ALL Columns?
The following SQL is generated:
SELECT [u].[WorkspaceId],
[u].[CreatedBy],
[u].[CreatedOn],
[u].[CreationTimestamp],
[u].[DeletedFlag],
[u].[DeletedTimestamp],
[u].[LastUpdateBy],
[u].[LastUpdateOn],
[u].[LastUpdateTimestamp],
[u].[WorkspaceDesciption],
[u].[WorkspaceLastOnline],
[u].[WorkspaceLocation],
[u].[WorkspaceLocked],
[u].[WorkspaceName]
FROM [Workspaces] AS [u]
WHERE [u].[WorkspaceId] IN (1)
ORDER BY [u].[WorkspaceId]

Error with SPPID's Interop.Llama library : System.Runtime.InteropServices.COMException (0x80000008): No DBConnect for Data_Dictionary

I'm having the following error usiing SmartPlant P&ID (SPPID) automation library Llama (Interop.Llama.dll):
System.Runtime.InteropServices.COMException (0x80000008): No DBConnect for Data_Dictionary
at Llama._LMEquipments.Collect(LMADataSource& DataSource, _LMAItem& Parent, String& RelationshipName, LMAFilter& Filter)
Here is the code that calls it:
Dim objDS As Llama.LMADataSource
Dim objEquips As Llama.LMEquipments
objDS = New Llama.LMADataSource
objDS.ProjectNumber = Project.SPPIDName & "!" & Project.SPPIDName
objDS.SiteNode = Project.SiteServer
objEquips = New Llama.LMEquipments
objEquips.Collect(objDS) ' throws Exception
Any ideas on what might be wrong?
SPPID is an engineering tool used to develop and manage piping and instrumentation diagrams. Llama is an automation library supplied with SPPID.
This means that your code can't find that specific project in SPPID available plant structures database. Beware that the ProjectNumber string is case sensitive .
In my case, all I had to do was to change project name, from PF2_REF to PF2_Ref (replaced last two letters for lowercase equivalents).

query ebay odata with linq

I am pulling information from eBay using their odata feed. I am trying to use linq to pull the specific information we are after. Using linq I can get down to the specific element holding the information we want. What I can't do is figure out how to query the element data to get the specific child elements I want. I could just parse it but really want to learn linq. I am using vb.net as the language. To get the element I am after I use the following:
Sub Main
dim ns = "http://ebayodata.cloudapp.net/"
dim url as string = "http://ebayodata.cloudapp.net/Items?search=1756-L65"
Using reader As XmlReader = XmlReader.Create(url)
While reader.Read()
If reader.NodeType = XmlNodeType.Element AndAlso reader.Name = "entry" Then
GetChildContentElements(reader)
End If
End While
End Using
End Sub
Private Sub GetChildContentElements(reader As XmlReader)
' move to first child
While reader.Read()
If reader.NodeType = XmlNodeType.Element AndAlso reader.Name = "m:properties" Then
Exit While
End If
End While
Dim bookXml As XElement = DirectCast(XNode.ReadFrom(reader), XElement)
Console.WriteLine(bookXml)
End Sub
One of the elements this returns looks like:
<m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
<d:Id>160917851201</d:Id>
<d:UserId>baltisales</d:UserId>
<d:Title>Allen Bradley 1756-L65 /B ControlLogix Processor 32MB Memory *60 DAYS WARRANTY!*</d:Title>
<d:Subtitle m:null="true"></d:Subtitle>
<d:SellingState>Active</d:SellingState>
<d:TimeLeft>P24DT2H25M33S</d:TimeLeft>
<d:Currency>USD</d:Currency>
<d:CurrentPrice m:type="Edm.Double">6446.14</d:CurrentPrice>
<d:MinimumToBid m:type="Edm.Double">6446.14</d:MinimumToBid>
<d:BidCount m:type="Edm.Int32">0</d:BidCount>
<d:Description m:null="true"></d:Description>
<d:QuantitySold m:type="Edm.Int32">0</d:QuantitySold>
<d:AutoPay m:type="Edm.Boolean">false</d:AutoPay>
<d:CharityId m:null="true"></d:CharityId>
<d:Country>US</d:Country>
<d:Compatibility m:null="true"></d:Compatibility>
<d:GalleryUrl>http://thumbs2.ebaystatic.com/m/m3Y01PfuyFhctnJiEet95Gw/140.jpg</d:GalleryUrl>
<d:GlobalId>EBAY-US</d:GlobalId>
<d:PostalCode>21209</d:PostalCode>
<d:ReturnsAccepted m:type="Edm.Boolean">true</d:ReturnsAccepted>
<d:PrimaryCategoryId>97184</d:PrimaryCategoryId>
<d:SecondaryCategoryId m:null="true"></d:SecondaryCategoryId>
<d:ViewItemUrl>http://www.ebay.com/itm/Allen-Bradley-1756-L65-B-ControlLogix-Processor-32MB-Memory-60-DAYS-WARRANTY-/160917851201?pt=BI_Control_Systems_PLCs</d:ViewItemUrl>
<d:PaymentMethods>PayPal ,VisaMC ,AmEx</d:PaymentMethods>
<d:Condition m:type="eBay.Model.Entities.Condition">
<d:Id m:type="Edm.Int32">3000</d:Id>
<d:Name>Used</d:Name>
</d:Condition>
<d:ListingInfo m:type="eBay.Model.Entities.ListingInfo">
<d:BestOfferEnabled m:type="Edm.Boolean">true</d:BestOfferEnabled>
<d:BuyItNowAvailable m:type="Edm.Boolean">false</d:BuyItNowAvailable>
<d:BuyItNowPrice m:type="Edm.Double" m:null="true"></d:BuyItNowPrice>
<d:ConvertedBuyItNowPrice m:type="Edm.Double" m:null="true"> </d:ConvertedBuyItNowPrice>
<d:Gift m:type="Edm.Boolean">false</d:Gift>
<d:ListingType>StoreInventory</d:ListingType>
<d:StartTime m:type="Edm.DateTime">2012-11-06T23:08:18Z</d:StartTime>
<d:EndTime m:type="Edm.DateTime">2013-04-05T23:13:18Z</d:EndTime>
</d:ListingInfo>
<d:Distance m:type="eBay.Model.Entities.Distance" m:null="true"></d:Distance>
<d:ShippingInformation m:type="eBay.Model.Entities.ShippingInformation">
<d:Delimiter m:null="true"></d:Delimiter>
<d:ExpeditedShipping m:type="Edm.Boolean">true</d:ExpeditedShipping>
<d:HandlingTime m:type="Edm.Int32">1</d:HandlingTime>
<d:OneDayShippingAvailable m:type="Edm.Boolean">true</d:OneDayShippingAvailable>
<d:ShippingServiceCost m:type="Edm.Double">0</d:ShippingServiceCost>
<d:ShippingType>FlatDomesticCalculatedInternational</d:ShippingType>
</d:ShippingInformation>
</m:properties>
I am struggling with querying the above to get the specific child elements we need to work with. The ":" in the tags seems to be confusing using namespaces. What I would like to do is to be able to query the element to get values for d:Id, d:UserId, d:Currentprice, etc. Any suggestions would be welcomed.
Try using WCF data services client. It can generate proxy classes for you that would simplify things. Refer to the documentation here.
Sample code for doing custom url's with generated WCF DS client,
const string baseAddress = "http://ebayodata.cloudapp.net/";
EBayData ebay = new EBayData(new Uri(baseAddress));
var items = ebay.Execute<Item>(new Uri(baseAddress + "Items?search=1756-L65"));
foreach (var item in items)
{
Console.WriteLine(item.Title);
}