How to OrderBy with XhtmlString?

Vote:
 

Is there any way to supply an OrderBy to XhtmlString type value?

In general, For a string value i.e. 

Contrary to popular belief, Lorem Ipsum... and There are many variations of passages..., It would sort the Contrary.. first based on alphabetical order. 

But for XhtmlString type value in Episerver which comes with HTML tags included with it, It is not easy to work with LinQ OrderBy.

I'm just wonering if is there any easy way to use OrderBy for following code snippet, Where the Title is type of XhtmlString - 

result = filters
.OrderBy(c => c.Title)
.Skip(skip).Take(take)
.GetContentResult<CorporateGuestReportingBlock>();

How could I order those type of strings in Episerver?

Thanks for your time.

#205853
Jul 25, 2019 11:30
Vote:
 

Hi Manoj,

Looking at your code snippet, I'm assuming you're using Find in which case you could look at indexing a string representation of your XHtmlString and sorting on that. You could do this by adding an additional property directly to your content type and marking it with the [RemoveHtmlTagsWhenIndexing] attribute but, as this property is only to be used for search, I'd add it using search indexing conventions to keep things tidy. Something like this:

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class InitialiseSearch : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        SearchClient.Instance.Conventions.ForInstancesOf<CorporateGuestReportingBlock>().IncludeField(x => x.Title.StripHtml());
    }

    public void Uninitialize(InitializationEngine context)
    {
    }
}

where the StripHtml extension looks like this and returns up to 1000 characters (which should be easily sufficient for sorting):

public static class SearchExtensions
{
    public static string StripHtml(this XhtmlString htmlField)
    {
        return htmlField == null ? string.Empty : EPiServer.Core.Html.TextIndexer.StripHtml(htmlField.ToHtmlString(), 1000);
    }
}

You would then be able to sort your search like this:

result = filters
.OrderBy(c => c.Title.StripHtml())
.Skip(skip).Take(take)
.GetContentResult<CorporateGuestReportingBlock>();
#205859
Jul 25, 2019 16:17
Vote:
 

Hey Paul,

Don't you think, we will need to pass IndexingModule as ModuleDependency? Just a guess :)

[ModuleDependency(typeof(IndexingModule))]
#205860
Jul 25, 2019 16:56
Paul Gruffydd - Jul 25, 2019 19:25
That's a fair comment though, as far as I'm aware, we don't have a dependency on the indexing module in this instance so it shouldn't be necessary to wait for it to initialise.
Vote:
 

Hey Paul, 

Thanks for looking into this, However none of this worked. I'm assuming because the .Title is still in not memory and it is just an expression for Find that's why it won't hit Extension method?

result = filters
.OrderBy(c => c.Title.StripHtml())
.Skip(skip).Take(take)
.Filter(c => c.UseAsPlaceholder.Match(false))
.GetContentResult<CorporatePressReleaseBlock>();

I also tried decorating property with  [RemoveHtmlTagsWhenIndexing] Attribute but with a failed attempt. 

Do you have any idea what may have happened? 

Appreciate your time.

#205861
Edited, Jul 25, 2019 17:20
Vote:
 

Hey Praful, 

I swapped out ModuleDependency from InitializationModule to IndexingModule but this doesn't do the trick.

Appreciate your time. 

#205864
Jul 25, 2019 17:19
Vote:
 

Hi Manoj,

Did you reindex the content (using the scheduled job in admin) after you made those changes? The code samples I provided modify the way the content is indexed, adding in a field to the content items in the index called "Title.StripHtml$$string". When you search or order on Title.StripHtml(), it doesn't run the extension method, instead it looks for the "Title.StripHtml$$string" field. If you haven't reindexed, that field won't be there.

If you just decorated your existing XhtmlString property with the [RemoveHtmlTagsWhenIndexing] attribute, it wouldn't really change anything as, to the best of my knowledge, this is already applied to the contents of XhtmlString properties.

#205865
Jul 25, 2019 17:21
Vote:
 

Hey Paul,

I guess the below line isn't working

htmlField.ToHtmlString()

See the debug mode analysis of code

Hey Manoj,

The following blog post have some code or you can implement your own extension method to convert the Html encode to plain text.

http://www.blackbeltcoder.com/Articles/strings/convert-html-to-text

Thanks

#205867
Jul 25, 2019 17:31
Vote:
 

Hi Praful,

The important bit is the call to "EPiServer.Core.Html.TextIndexer.StripHtml" as that's what removes the tags. The ToHtmlString() method of the XHtmlString just gives us a string representation of the HTML content of the XHtmlString property so the result in your screenshot is what I'd expect for just that part.

#205868
Jul 25, 2019 17:39
Praful Jangid - Jul 26, 2019 4:18
Gotcha, thanks Paul.
Vote:
 

Hey Paul, 

Thankyou it worked after reindexing the content. I also could verify it created the additional field while stripping HTML.

#205869
Jul 25, 2019 17:46